前言

在asp.net core中,我巨硬引入了DI容器,我们可以在不使用第三方插件的情况下轻松实现依赖注入。如下代码:

 1         // This method gets called by the runtime. Use this method to add services to the container.
 2         public void ConfigureServices(IServiceCollection services)
 3         {
 4             //services.RegisterAssembly("IServices");
 5             services.AddSingleton<IUserService, UserService>();
 6             // Add framework services.
 7             services.AddMvc();
 8             services.AddMvcCore()
 9                 .AddApiExplorer();
10             services.AddSwaggerGen(options =>
11             {
12                 options.SwaggerDoc("v1", new Info()
13                 {
14                     Title = "Swagger测试",
15                     Version = "v1",
16                     Description = "Swagger测试RESTful API ",
17                     TermsOfService = "None",
18                     Contact = new Contact
19                     {
20                         Name = "来来吹牛逼",
21                         Email = "xxoo123@outlook.com"
22                     },
23                 });
24                 //设置xml注释文档,注意名称一定要与项目名称相同
25                 var filePath = Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "WebApi.xml");
26                 options.IncludeXmlComments(filePath);
27             });
28         }

View Code

但是,随着公司业务的扩大,系统项目的功能模块急剧扩张,新增了不下百个或者千个Repository和Service(有点夸张了...),这时候如此单纯滴注入就有点操蛋了。

打懒主意

我可不可以通过反射技术来实现对程序集的注入呢??

试试就试试

首先,我私自先制定一些类名的约束。规则嘛,反正是自己定。比如:

  • UserService --> IUserService
  • UserRepository --> IUserRepository
  • ......
  • ClassName --> IClassName

好了,我们下面开始编码:

 1     /// <summary>
 2     /// IServiceCollection扩展
 3     /// </summary>
 4     public static class ServiceExtension
 5     {
 6         /// <summary>
 7         /// 用DI批量注入接口程序集中对应的实现类。
 8         /// <para>
 9         /// 需要注意的是,这里有如下约定:
10         /// IUserService --> UserService, IUserRepository --> UserRepository.
11         /// </para>
12         /// </summary>
13         /// <param name="service"></param>
14         /// <param name="interfaceAssemblyName">接口程序集的名称(不包含文件扩展名)</param>
15         /// <returns></returns>
16         public static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName)
17         {
18             if (service == null)
19                 throw new ArgumentNullException(nameof(service));
20             if (string.IsNullOrEmpty(interfaceAssemblyName))
21                 throw new ArgumentNullException(nameof(interfaceAssemblyName));
22
23             var assembly = RuntimeHelper.GetAssembly(interfaceAssemblyName);
24             if (assembly == null)
25             {
26                 throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found");
27             }
28
29             //过滤掉非接口及泛型接口
30             var types = assembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType);
31
32             foreach (var type in types)
33             {
34                 var implementTypeName = type.Name.Substring(1);
35                 var implementType = RuntimeHelper.GetImplementType(implementTypeName, type);
36                 if (implementType != null)
37                     service.AddSingleton(type, implementType);
38             }
39             return service;
40         }
41
42         /// <summary>
43         /// 用DI批量注入接口程序集中对应的实现类。
44         /// </summary>
45         /// <param name="service"></param>
46         /// <param name="interfaceAssemblyName">接口程序集的名称(不包含文件扩展名)</param>
47         /// <param name="implementAssemblyName">实现程序集的名称(不包含文件扩展名)</param>
48         /// <returns></returns>
49         public static IServiceCollection RegisterAssembly(this IServiceCollection service, string interfaceAssemblyName, string implementAssemblyName)
50         {
51             if (service == null)
52                 throw new ArgumentNullException(nameof(service));
53             if(string.IsNullOrEmpty(interfaceAssemblyName))
54                 throw new ArgumentNullException(nameof(interfaceAssemblyName));
55             if (string.IsNullOrEmpty(implementAssemblyName))
56                 throw new ArgumentNullException(nameof(implementAssemblyName));
57
58             var interfaceAssembly = RuntimeHelper.GetAssembly(interfaceAssemblyName);
59             if (interfaceAssembly == null)
60             {
61                 throw new DllNotFoundException($"the dll \"{interfaceAssemblyName}\" not be found");
62             }
63
64             var implementAssembly = RuntimeHelper.GetAssembly(implementAssemblyName);
65             if (implementAssembly == null)
66             {
67                 throw new DllNotFoundException($"the dll \"{implementAssemblyName}\" not be found");
68             }
69
70             //过滤掉非接口及泛型接口
71             var types = interfaceAssembly.GetTypes().Where(t => t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsGenericType);
72
73             foreach (var type in types)
74             {
75                 //过滤掉抽象类、泛型类以及非class
76                 var implementType = implementAssembly.DefinedTypes
77                     .FirstOrDefault(t => t.IsClass && !t.IsAbstract && !t.IsGenericType &&
78                                          t.GetInterfaces().Any(b => b.Name == type.Name));
79                 if (implementType != null)
80                 {
81                     service.AddSingleton(type, implementType.AsType());
82                 }
83             }
84
85             return service;
86         }
87     }

View Code

附上RuntimeHelper.cs的代码:

 1     public class RuntimeHelper
 2     {
 3         /// <summary>
 4         /// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
 5         /// </summary>
 6         /// <returns></returns>
 7         public static IList<Assembly> GetAllAssemblies()
 8         {
 9             var list = new List<Assembly>();
10             var deps = DependencyContext.Default;
11             var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package");//排除所有的系统程序集、Nuget下载包
12             foreach (var lib in libs)
13             {
14                 try
15                 {
16                     var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
17                     list.Add(assembly);
18                 }
19                 catch (Exception)
20                 {
21                     // ignored
22                 }
23             }
24             return list;
25         }
26
27         public static Assembly GetAssembly(string assemblyName)
28         {
29             return GetAllAssemblies().FirstOrDefault(assembly => assembly.FullName.Contains(assemblyName));
30         }
31
32         public static IList<Type> GetAllTypes()
33         {
34             var list = new List<Type>();
35             foreach (var assembly in GetAllAssemblies())
36             {
37                 var typeInfos = assembly.DefinedTypes;
38                 foreach (var typeInfo in typeInfos)
39                 {
40                     list.Add(typeInfo.AsType());
41                 }
42             }
43             return list;
44         }
45
46         public static IList<Type> GetTypesByAssembly(string assemblyName)
47         {
48             var list = new List<Type>();
49             var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(assemblyName));
50             var typeInfos = assembly.DefinedTypes;
51             foreach (var typeInfo in typeInfos)
52             {
53                 list.Add(typeInfo.AsType());
54             }
55             return list;
56         }
57
58         public static Type GetImplementType(string typeName, Type baseInterfaceType)
59         {
60             return GetAllTypes().FirstOrDefault(t =>
61             {
62                 if (t.Name == typeName &&
63                     t.GetTypeInfo().GetInterfaces().Any(b => b.Name == baseInterfaceType.Name))
64                 {
65                     var typeInfo = t.GetTypeInfo();
66                     return typeInfo.IsClass && !typeInfo.IsAbstract && !typeInfo.IsGenericType;
67                 }
68                 return false;
69             });
70         }
71     }

View Code

好了,到此就基本完成了,记得在Startup.cs加上:

1 // This method gets called by the runtime. Use this method to add services to the container.
2         public IServiceProvider ConfigureServices(IServiceCollection services)
3         {
4             services.RegisterAssembly("IServices");
5
6             // Add framework services.
7             services.AddMvc();
8         }

View Code

总结

小记一下,好记性不如烂笔头。

转载于:https://www.cnblogs.com/zengxw/p/6864311.html

【懒人有道】在asp.net core中实现程序集注入相关推荐

  1. ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理

    ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...

  2. ASP.NET Core 中的依赖注入

    什么是依赖注入 软件设计原则中有一个依赖倒置原则(DIP),为了更好的解耦,讲究要依赖于抽象,不要依赖于具体.而控制反转(Ioc)就是这样的原则的其中一个实现思路, 这个思路的其中一种实现方式就是依赖 ...

  3. ASP.NET Core中的依赖注入(2):依赖注入(DI)

    IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...

  4. 在 ASP.NET Core 中安装 MVC

    目录 本文出自<从零开始学 ASP.NET CORE MVC>目录  视频课程效果更佳:从零开始学 Asp.Net Core MVC 在ASP.NET Core 中安装 MVC 在本视频中 ...

  5. winform防止sqlserver注入_ASP.NET Core 中的 依赖注入介绍

    ASP.NET Core 依赖注入 HomeController public class HomeController : Controller { private IStudentReposito ...

  6. 如何简单的在 ASP.NET Core 中集成 JWT 认证?

    前情提要:ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统 文章超长预警(1万字以上),不想看全部实现过程的同学可以直接跳转到末尾查看成果或者一键安装相关的 nuget 包 自上一 ...

  7. .ASP NET Core中缓存问题案例

    本篇博客中,我将描述一个关于会话状态(Session State)的问题, 这个问题我已经被询问了好几次了. 问题的场景 创建一个新的ASP.NET Core应用程序 一个用户在会话状态中设置了一个字 ...

  8. 使用Redis Stream来做消息队列和在Asp.Net Core中的实现

    Redis - Wikipedia 写在前面 我一直以来使用redis的时候,很多低烈度需求(并发要求不是很高)需要用到消息队列的时候,在项目本身已经使用了Redis的情况下都想直接用Redis来做消 ...

  9. ASP.NET Core中的内存缓存

    ASP.NET Core中的内存中缓存 让我们看看如何通过缓存优化ASP.NET Core应用程序性能 我相信,在我们的工作中,每个人都收到来自客户的请求或来自我们应用程序用户的反馈,以提高响应速度. ...

最新文章

  1. KMP算法的理解,伪代码,c代码实现
  2. OpenJDK 14 性能保持提升,但 OpenJDK 8 仍是最强王者
  3. 人工智能工程师学习路线及具备的5项基本技能
  4. 英语自动提取高频词_斑马英语提分营免费体验课
  5. App for Android (1) —— 环境搭建
  6. 一文捋清Android消息机制
  7. 开源战略游戏源码_开源的历史告诉我们关于战略优势的知识
  8. java搜寻范围在哪设定_查找值在Java中的范围
  9. SVN 中文工具(Tools)
  10. 报销金额数字小写转大写 总结
  11. WSO2 ESB 5.0.0 的一些控制台显示配置
  12. NIOSII 软核的流水灯
  13. 1080i和1080p区别
  14. C++ 赛码打字编程题
  15. 结对项目——最长英语单词链
  16. 2023蓝牙耳机性价比推荐:高品质蓝牙耳机盘点分享
  17. API 接口批量测试
  18. 回文树/回文自动机 引入
  19. 维基解密说会帮科技公司解决漏洞 可后者并不买账
  20. 基于图像处理的路面裂缝检测系统设计与研究

热门文章

  1. C# GridView 分页显示
  2. Node.js 修复4个漏洞
  3. Cerberus 银行木马开发团队解散,源代码5万美元起拍
  4. 某 iOS 零点击 0day 漏洞已存在8年之久且正遭利用?苹果称正在调查并将推出补丁...
  5. RSAC|苹果设备的最大威胁是逆向后重部署的恶意软件
  6. 「大学生学编程系列」第六篇:如何学习C语言?
  7. android studio gradle 更新方法。
  8. Apache Phoenix学习记录(SQL on HBase)
  9. 如何启动一个本地静态服务器
  10. Python计算绘图——曲线拟合问题(转)