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     }
  • 相关阅读:
    Two strings CodeForces
    Dasha and Photos CodeForces
    Largest Beautiful Number CodeForces
    Timetable CodeForces
    Financiers Game CodeForces
    AC日记——整理药名 openjudge 1.7 15
    AC日记——大小写字母互换 openjudge 1.7 14
    AC日记——将字符串中的小写字母换成大写字母 openjudge 1.7 13
    AC日记——加密的病历单 openjudge 1.7 12
    AC日记——潜伏着 openjudge 1.7 11
  • 原文地址:https://www.cnblogs.com/migomiddle/p/11848358.html
Copyright © 2011-2022 走看看