简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个开源库,旨在简化 ASP.NET Core 应用程序中依赖注入(DI)的注册过程。通过自动扫描程序集中的类型并根据提供的规则自动注册服务。
基本使用
使用 NuGet 包管理器安装:
dotnet add package Scrutor
步骤
- 选择器(Selector):指定要注册的服务实现。
- 注册策略(Registration Strategy):处理重复服务的策略。
- 服务(Services):指定服务的具体实现。
- 生命周期(Lifetime):服务的生命周期,如 Singleton、Scoped、Transient。
- 选择程序集:指定从哪个程序集中扫描类型。
services.Scan(scan => scan .FromAssemblyOf<MyClass>(); // 从包含MyClass的程序集中扫描
- 添加类:过滤需要注册的类。
services.Scan(scan => scan .FromAssemblyOf<MyClass>() .AddClasses(classes => classes.Where(t => t.Name.EndsWith("Service"))); // 只注册以Service结尾的类
- 指定注册方式:指定类应该注册为哪些接口。
services.Scan(scan => scan .FromAssemblyOf<MyClass>() .AddClasses(classes => classes.Where(t => t.Name.EndsWith("Service"))) .AsImplementedInterfaces(); // 注册为实现的所有接口
- 设置生命周期:为注册的服务设置生命周期。
services.Scan(scan => scan .FromAssemblyOf<MyClass>() .AddClasses(classes => classes.Where(t => t.Name.EndsWith("Service"))) .AsImplementedInterfaces() .WithScopedLifetime(); // 设置为Scoped生命周期
进阶使用
进行服务扫描(Scanning)
- FromAssemblyOf
() 从包含指定类型T的程序集中扫描服务。 - FromAssembliesOf(params Type[] types)可以指定多个类型,Scrutor 将扫描包含这些类型的所有程序集。
- FromCallingAssembly()扫描调用
Scan方法的程序集。 - FromExecutingAssembly()扫描正在执行
Scan方法的程序集。 - FromEntryAssembly()扫描应用程序的入口程序集(通常是包含
Main方法的程序集)。 - 等等...
进行服务装饰(Decoration)
服务装饰是一种在不改变现有服务实现的情况下,动态地为服务添加额外功能的技术。
使用案例
装饰器模式,允许你在不修改现有类的情况下为服务添加行为。例如,为 IMessageSender 接口添加一个记录日志的装饰器:
public interface IMessageSender { void SendMessage(string message); } public class EmailMessageSender : IMessageSender { public void SendMessage(string message) { Console.WriteLine($"Sending email: {message}"); } } public class LoggingMessageSender : IMessageSender { private readonly IMessageSender _inner; public LoggingMessageSender(IMessageSender inner) { _inner = inner; } public void SendMessage(string message) { Console.WriteLine("Starting to send message..."); _inner.SendMessage(message); Console.WriteLine("Message sent successfully."); } } // 使用 Scrutor 注册服务和装饰器 services.Scan(scan => scan .FromAssemblyOf<IMessageSender>() .AddClasses(classes => classes.AssignableTo<IMessageSender>()) .AsImplementedInterfaces() .WithTransientLifetime()); services.Decorate<IMessageSender, LoggingMessageSender>();
生命周期管理
想要为特定服务设置不同的生命周期,可以链式调用不同的生命周期设置
services.Scan(scan => scan .FromAssemblyOf<CombinedService>() .AddClasses(classes => classes.AssignableTo<ICombinedService>()) // 过滤服务 .AsSelfWithInterfaces() // 注册为接口 .WithSingletonLifetime()) // 设置为 Singleton 生命周期 // 对于其他服务,设置 Scoped 生命周期 .AddClasses(x => x.AssignableTo(typeof(IOpenGeneric<>))) // 可以关闭泛型类型 .AsMatchingInterface() .WithScopedLifetime(); // 设置为 Scoped 生命周期
多重过滤
services.Scan(scan => scan .FromAssemblyOf<MyService>() .AddClasses() .UsingRegistrationStrategy(RegistrationStrategy.Skip) // 如果服务已存在,则跳过注册 .AsSelf() .WithTransientLifetime());
链式注册
Scrutor 允许你将多个扫描整合成一个调用链,为不同的类应用不同的规则子集:
services.Scan(scan => scan .FromAssemblyOf<Startup>() .AddClasses(classes => classes.Where(t => t.Name.EndsWith("Repository"))) .AsImplementedInterfaces() .WithTransientLifetime() .AddClasses(classes => classes.Where(t => t.Name.EndsWith("Service"))) .AsImplementedInterfaces() .WithScopedLifetime());
总结
Scrutor 在实际项目中简化依赖注入的配置工作,特别是在大型项目中,提供了灵活的扫描和注册机制,使得服务注册更加简洁和可维护。
欢迎关注我的公众号“Net分享”,技术文章第一时间推送,随缘更新 , 分享一些你可能注意不到的细节。