博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【懒人有道】在asp.net core中实现程序集注入
阅读量:7078 次
发布时间:2019-06-28

本文共 8250 字,大约阅读时间需要 27 分钟。

前言

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

 

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

打懒主意

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

试试就试试

首先,我私自先制定一些类名的约束。规则嘛,反正是自己定。比如:
  • UserService --> IUserService
  • UserRepository --> IUserRepository
  • ......
  • ClassName --> IClassName
好了,我们下面开始编码:
1 ///  2     /// IServiceCollection扩展 3     ///  4     public static class ServiceExtension 5     { 6         ///  7         /// 用DI批量注入接口程序集中对应的实现类。 8         /// 
9 /// 需要注意的是,这里有如下约定:10 /// IUserService --> UserService, IUserRepository --> UserRepository.11 ///
12 ///
13 /// 14 /// 接口程序集的名称(不包含文件扩展名)15 ///
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 /// 43 /// 用DI批量注入接口程序集中对应的实现类。44 /// 45 /// 46 /// 接口程序集的名称(不包含文件扩展名)47 /// 实现程序集的名称(不包含文件扩展名)48 ///
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 //过滤掉抽象类、泛型类以及非class76 var implementType = implementAssembly.DefinedTypes77 .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 }

 

附上RuntimeHelper.cs的代码:
1 public class RuntimeHelper 2     { 3         ///  4         /// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包 5         ///  6         /// 
7 public static IList
GetAllAssemblies() 8 { 9 var list = new List
();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 try15 {16 var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));17 list.Add(assembly);18 }19 catch (Exception)20 {21 // ignored22 }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
GetAllTypes()33 {34 var list = new List
();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
GetTypesByAssembly(string assemblyName)47 {48 var list = new List
();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 }

 

好了,到此就基本完成了,记得在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             services.Configure
( 6 options => options.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5));//设置缓存有效时间为5分钟。 7 8 // Add framework services. 9 services.AddMvc();10 11 return services.BuilderInterceptableServiceProvider(builder => builder.SetDynamicProxyFactory());12 }

 

总结

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

转载地址:http://xxpml.baihongyu.com/

你可能感兴趣的文章
安吉斯媒体:流程化运作助推一站式管理
查看>>
云存储基础架构决策:公有 VS. 私有
查看>>
中国人工智能学会通讯——构建强健的人工智能:原因及方式 5. 使用更大的模型...
查看>>
吉林交警携手高德地图 开展“互联网+交通管理”
查看>>
云栖科技这家公司切入企业级文档云市场,希望解决移动和安全两个痛点
查看>>
在用苹果Mac OS X操作系统吗?那你得小心了……
查看>>
2014年11月11日
查看>>
秒杀WiFi 新技术让你一秒下载23部电影
查看>>
物联网时代三大标准齐头并进 互为补充
查看>>
阿里云成为Linux基金会金牌会员
查看>>
大数据时代 数据中心面临三大挑战
查看>>
《网络空间欺骗:构筑欺骗防御的科学基石》一3.3.4 识别和量化恶意软件的指标...
查看>>
自动化是任何云计算的基础
查看>>
密码提取神器 mimikatz 现已支持Windows 10 RS2
查看>>
老生常谈数据中心节能
查看>>
Check Point 指出2016 下半年勒索软件倍增
查看>>
微服务和容器对企业带来什么样的影响?
查看>>
如何掌握好应用程序的数据和未来发展
查看>>
“免费WiFi午餐”到底要怎么“吃”?
查看>>
2016首都网络安全日系列活动之打击电信网络诈骗宣传体验展
查看>>