.netcore之DI批量注入(支持泛型) - xms

一旦系统内模块比较多,按DI标准方法去逐个硬敲AddScoped/AddSingleton/AddTransient缺乏灵活性且效率低下,所以批量注入提供了很大的便捷性,特别是对于泛型的服务类,下面介绍一下我在xms系统中应用的DI便捷工具:

1. 先来个dll助手

无外部依赖,可直接复用

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Diagnostics;
  4 using System.IO;
  5 using System.Reflection;
  6 using System.Runtime.Loader;
  7 
  8 namespace Xms.Infrastructure.Utility
  9 {
 10     public class AssemblyHelper
 11     {
 12         public static List<Assembly> GetAssemblies(string searchPattern = "")
 13         {
 14             List<Assembly> assemblies = new List<Assembly>();
 15             if (searchPattern.HasValue())
 16             {
 17                 DirectoryInfo root = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
 18                 foreach (FileInfo f in root.GetFiles(searchPattern))
 19                 {
 20                     assemblies.Add(AssemblyLoadContext.Default.LoadFromAssemblyPath(f.FullName));
 21                 }
 22             }
 23             else
 24             {
 25                 assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies());
 26             }
 27             return assemblies;
 28         }
 29 
 30         public static List<Type> GetClassOfType(Type assignTypeFrom, string searchPattern = "")
 31         {
 32             var assemblies = GetAssemblies(searchPattern);
 33             var result = new List<Type>();
 34             try
 35             {
 36                 foreach (var a in assemblies)
 37                 {
 38                     Type[] types = a.GetTypes();
 39 
 40                     if (types == null)
 41                     {
 42                         continue;
 43                     }
 44 
 45                     foreach (var t in types)
 46                     {
 47                         if (!assignTypeFrom.IsAssignableFrom(t) && (!assignTypeFrom.IsGenericTypeDefinition || !DoesTypeImplementOpenGeneric(t, assignTypeFrom)))
 48                         {
 49                             continue;
 50                         }
 51 
 52                         if (t.IsInterface)
 53                         {
 54                             continue;
 55                         }
 56 
 57                         if (t.IsAbstract)
 58                         {
 59                             continue;
 60                         }
 61 
 62                         result.Add(t);
 63                     }
 64                 }
 65             }
 66             catch (ReflectionTypeLoadException ex)
 67             {
 68                 var msg = string.Empty;
 69                 foreach (var e in ex.LoaderExceptions)
 70                 {
 71                     msg += e.Message + Environment.NewLine;
 72                 }
 73 
 74                 var fail = new Exception(msg, ex);
 75                 Debug.WriteLine(fail.Message, fail);
 76 
 77                 throw fail;
 78             }
 79 
 80             return result;
 81         }
 82 
 83         public static bool DoesTypeImplementOpenGeneric(Type type, Type openGeneric)
 84         {
 85             try
 86             {
 87                 var genericTypeDefinition = openGeneric.GetGenericTypeDefinition();
 88                 foreach (var implementedInterface in type.FindInterfaces((objType, objCriteria) => true, null))
 89                 {
 90                     if (!implementedInterface.IsGenericType)
 91                     {
 92                         continue;
 93                     }
 94 
 95                     var isMatch = genericTypeDefinition.IsAssignableFrom(implementedInterface.GetGenericTypeDefinition());
 96                     return isMatch;
 97                 }
 98 
 99                 return false;
100             }
101             catch
102             {
103                 return false;
104             }
105         }
106     }
107 }

2. 服务自动注册接口

用于每个模块注册自己的服务,达到模块的高度自治的目的

 1 using Microsoft.Extensions.Configuration;
 2 using Microsoft.Extensions.DependencyInjection;
 3 
 4 namespace Xms.Infrastructure.Inject
 5 {
 6     /// <summary>
 7     /// 服务自动注册接口
 8     /// </summary>
 9     public interface IServiceRegistrar
10     {
11         void Add(IServiceCollection services, IConfiguration configuration);
12 
13         int Order { get; }
14     }
15 }

3. DI服务扩展方法

 1 using Microsoft.Extensions.Configuration;
 2 using Microsoft.Extensions.DependencyInjection;
 3 using System;
 4 using Xms.Infrastructure.Inject;
 5 using Xms.Infrastructure.Utility;
 6 
 7 namespace Xms.Core
 8 {
 9     public static class ServiceCollectionExtensions
10     {
11         public static IServiceCollection RegisterAll(this IServiceCollection services, IConfiguration configuration)
12         {
13             var types = AssemblyHelper.GetClassOfType(typeof(IServiceRegistrar), "Xms.*.dll");
14             foreach (var t in types)
15             {
16                 var instance = (IServiceRegistrar)Activator.CreateInstance(t);
17                 instance.Add(services, configuration);
18             }
19             return services;
20         }
21 
22         public static IServiceCollection RegisterScope<TService>(this IServiceCollection services)
23         {
24             var serviceType = typeof(TService);
25             return Register(services, serviceType, ServiceLifetime.Scoped);
26         }
27 
28         public static IServiceCollection RegisterScope(this IServiceCollection services, Type serviceType)
29         {
30             return Register(services, serviceType, ServiceLifetime.Scoped);
31         }
32 
33         public static IServiceCollection Register(this IServiceCollection services, Type serviceType, ServiceLifetime serviceLifetime)
34         {
35             var implementTypes = AssemblyHelper.GetClassOfType(serviceType, "Xms.*.dll");
36             if (serviceType.IsGenericType)
37             {
38                 foreach (var impl in implementTypes)
39                 {
40                     var it = impl.FindInterfaces((type, criteria) =>
41                     {
42                         var isMatch = type.IsGenericType && ((Type)criteria).IsAssignableFrom(type.GetGenericTypeDefinition());
43                         return isMatch;
44                     }, serviceType);
45                     foreach (var i in it)
46                     {
47                         services.Add(new ServiceDescriptor(i, impl, serviceLifetime));
48                     }
49                 }
50             }
51             else
52             {
53                 foreach (var impl in implementTypes)
54                 {
55                     services.Add(new ServiceDescriptor(serviceType, impl, serviceLifetime));
56                 }
57             }
58             return services;
59         }
60     }
61 }

4. 使用示例

比如下面的一个事件发布服务类,多个消费者服务类,实现了消费者的动态注册,大大提高了系统的灵活性、扩展性

 1     /// <summary>
 2     /// 事件模块服务注册
 3     /// </summary>
 4     public class ServiceRegistrar : IServiceRegistrar
 5     {
 6         public int Order => 1;
 7 
 8         public void Add(IServiceCollection services, IConfiguration configuration)
 9         {
10             //event publisher
11             services.AddScoped<Event.Abstractions.IEventPublisher, Event.EventPublisher>();
12             //event consumers
13             services.RegisterScope(typeof(Event.Abstractions.IConsumer<>));
14         }
15     }

 

 

posted @ 2019-11-13 13:49  斗半米哥  阅读(3938)  评论(1编辑  收藏  举报