前言
在ASP.NET Core的应用程序编程开发中,依赖注入(DI)是不可回避的技术选项,因为ASP.NET Core的底层设计架构就考虑了依赖注入(DI)。所以,你不会依赖注入(DI),那么在ASP.NET Core的应用程序编程开发中是混不下去的。
至于依赖注入是什么,依赖注入在ASP.NET Core是的作用等等话题,请查阅其他资料。本文的重点是给大家分享一些关于ASP.NET Core 2.x 中如何自动扫描应用程序中的依赖注入(DI)的接口及实现并完成依赖的自动注册的方法。
硬编码依赖注入的思考
使用过Autofac
这个依赖注入组件的同学(特别是深入使用过的)应该清楚,依赖注入是需要提供接口以及其对应的实现的。在Autofac依赖注入组件中,如果使用熟练之后,我们不可能一个一个接口和实现去硬编码,类似这样的:
private void AutofacRegister()
{
var builder = new ContainerBuilder();
//注册MvcApplication程序集中所有的控制器
builder.RegisterControllers(typeof(MvcApplication).Assembly);
//注册仓储层服务
builder.RegisterType<PostRepository>().As<IPostRepository>();
//注册服务层服务
builder.RegisterType<PostService>().As<IPostService>();
//注册过滤器
builder.RegisterFilterProvider();
var container = builder.Build();
//设置依赖注入解析器
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
更多关于Autofac
的使用,在我的关于ASP.NET MVC 5的系列文章中也有详细的介绍和说明,请参考系列文章:一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar]
其中,以下方式为硬编码的依赖注入的注册方式:
//注册仓储层服务
builder.RegisterType<PostRepository>().As<IPostRepository>();
//注册服务层服务
builder.RegisterType<PostService>().As<IPostService>();
试想一下,我们每增加一个接口以及其实现的时候,是不是需要在这里硬编码注册一行代码呢?项目小还好,但当我们的项目变得庞大之后,这里的依赖注入怎么来维护呢?
人是会思考的动物,特别是程序猿!!!
这时,我们就要想办法了,想一下有没有一劳永逸的办法,即有没有办法实现依赖注入的动态注册,不管接口及实现怎么变化,我们只需按照一个规定来定义和实现接口。应用程序就能自动扫描并注册这些程序集中的接口和对应实现类,完成依赖注入的自动注册呢?
文章都写到这里了,办法肯定是有的。 以下就提供两种具体的实现方案。
ASP.NET Core 2 中自动扫描应用程序中的依赖注入并完成自动注册
方案一
使用反射加载程序集,手动挺扫描所有的服务依赖,然后将这个服务依赖添加到服务容器中,具体实现代码如下:
public static void ResolveAllTypes(this IServiceCollection services, string solutionPrefix, params string[] projectSuffixes)
{
//solutionPrefix 解决方案名称
//projectSuffixes 需要扫描的项目名称集合
//注意: 如果使用此方法,必须提供需要扫描的项目名称
var allAssemblies = new List<Assembly>();
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
foreach (var dll in Directory.GetFiles(path, "*.dll"))
allAssemblies.Add(Assembly.LoadFile(dll));
var types = new List<Type>();
foreach (var assembly in allAssemblies)
{
if (assembly.FullName.StartsWith(solutionPrefix))
{
foreach (var assemblyDefinedType in assembly.DefinedTypes)
{
if (projectSuffixes.Any(x => assemblyDefinedType.Name.EndsWith(x)))
{
types.Add(assemblyDefinedType.AsType());
}
}
}
}
var implementTypes = types.Where(x => x.IsClass).ToList();
foreach (var implementType in implementTypes)
{
//接口和实现的命名规则为:"AService"类实现了"IAService"接口,你也可以自定义规则
var interfaceType = implementType.GetInterface("I" + implementType.Name);
if (interfaceType != null)
{
services.Add(new ServiceDescriptor(interfaceType, implementType,
ServiceLifetime.Scoped));
}
}
}
方案二
github中有.NET开发者已经开发出了这种需求的扩展组件,地址为:Scrutor,此组件可以自动地发现并注册指定的服务
public interface IDependency
{
}
// 自动地发现并注册指定的服务,这些服务都实现了IDependency接口
services.Scan(
x =>
{
var entryAssembly = Assembly.GetEntryAssembly();
var referencedAssemblies = entryAssembly.GetReferencedAssemblies().Select(Assembly.Load);
var assemblies = new List<Assembly> { entryAssembly }.Concat(referencedAssemblies);
x.FromAssemblies(assemblies)
.AddClasses(classes => classes.AssignableTo(typeof(IDependency)))
.AsImplementedInterfaces()
.WithScopedLifetime();
});
版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。
发表评论
登录用户才能发表评论, 请 登 录 或者 注册