zoukankan      html  css  js  c++  java
  • .netcore之DI批量注入(支持泛型)

    一旦系统内模块比较多,按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     }
  • 相关阅读:
    jQuery之选择器
    JAVA之网页截屏
    AJAX之JSON
    JSP之AJAX
    JSP之邮箱检验
    【16】LRUChache
    hashmap与currentHashMap
    Day1 工厂模式
    D0 设计模式
    【15】【有点特殊的dp】 剪绳子
  • 原文地址:https://www.cnblogs.com/migomiddle/p/11848358.html
Copyright © 2011-2022 走看看