【懒人有道】在asp.net core中实现程序集注入
前言
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中实现程序集注入相关推荐
- ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理
ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...
- ASP.NET Core 中的依赖注入
什么是依赖注入 软件设计原则中有一个依赖倒置原则(DIP),为了更好的解耦,讲究要依赖于抽象,不要依赖于具体.而控制反转(Ioc)就是这样的原则的其中一个实现思路, 这个思路的其中一种实现方式就是依赖 ...
- ASP.NET Core中的依赖注入(2):依赖注入(DI)
IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...
- 在 ASP.NET Core 中安装 MVC
目录 本文出自<从零开始学 ASP.NET CORE MVC>目录 视频课程效果更佳:从零开始学 Asp.Net Core MVC 在ASP.NET Core 中安装 MVC 在本视频中 ...
- winform防止sqlserver注入_ASP.NET Core 中的 依赖注入介绍
ASP.NET Core 依赖注入 HomeController public class HomeController : Controller { private IStudentReposito ...
- 如何简单的在 ASP.NET Core 中集成 JWT 认证?
前情提要:ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统 文章超长预警(1万字以上),不想看全部实现过程的同学可以直接跳转到末尾查看成果或者一键安装相关的 nuget 包 自上一 ...
- .ASP NET Core中缓存问题案例
本篇博客中,我将描述一个关于会话状态(Session State)的问题, 这个问题我已经被询问了好几次了. 问题的场景 创建一个新的ASP.NET Core应用程序 一个用户在会话状态中设置了一个字 ...
- 使用Redis Stream来做消息队列和在Asp.Net Core中的实现
Redis - Wikipedia 写在前面 我一直以来使用redis的时候,很多低烈度需求(并发要求不是很高)需要用到消息队列的时候,在项目本身已经使用了Redis的情况下都想直接用Redis来做消 ...
- ASP.NET Core中的内存缓存
ASP.NET Core中的内存中缓存 让我们看看如何通过缓存优化ASP.NET Core应用程序性能 我相信,在我们的工作中,每个人都收到来自客户的请求或来自我们应用程序用户的反馈,以提高响应速度. ...
最新文章
- KMP算法的理解,伪代码,c代码实现
- OpenJDK 14 性能保持提升,但 OpenJDK 8 仍是最强王者
- 人工智能工程师学习路线及具备的5项基本技能
- 英语自动提取高频词_斑马英语提分营免费体验课
- App for Android (1) —— 环境搭建
- 一文捋清Android消息机制
- 开源战略游戏源码_开源的历史告诉我们关于战略优势的知识
- java搜寻范围在哪设定_查找值在Java中的范围
- SVN 中文工具(Tools)
- 报销金额数字小写转大写 总结
- WSO2 ESB 5.0.0 的一些控制台显示配置
- NIOSII 软核的流水灯
- 1080i和1080p区别
- C++ 赛码打字编程题
- 结对项目——最长英语单词链
- 2023蓝牙耳机性价比推荐:高品质蓝牙耳机盘点分享
- API 接口批量测试
- 回文树/回文自动机 引入
- 维基解密说会帮科技公司解决漏洞 可后者并不买账
- 基于图像处理的路面裂缝检测系统设计与研究