首页 / ASP.NET Core / 正文

[ASP.NET Core]ASP.NET Core 2.x 中如何自动扫描应用程序中的依赖注入(DI)的接口及实现并完成依赖的自动注册?

4715 发布于: 2018-05-25 读完约需12分钟

前言

在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();
        });

版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。

上一篇: [C#].NET/C#应用程序编程开发中从字符串中查找并提取数字的方法有哪些呢?

下一篇: [SQLite]SQLite数据库中如何使用SQL语句列出所打开的数据库的所有数据表的信息?

本文永久链接码友网 » [ASP.NET Core]ASP.NET Core 2.x 中如何自动扫描应用程序中的依赖注入(DI)的接口及实现并完成依赖的自动注册?

分享扩散:

发表评论

登录用户才能发表评论, 请 登 录 或者 注册