http://www.cnblogs.com/zengxw/p/6864311.html
在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 = "[email protected]"
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 /// <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 }附上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 }好了,到此就基本完成了,记得在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 }
