AspectCore和MSDI 实现Name注册以及解析对象

  • AspectCore和MSDI 实现Name注册以及解析对象已关闭评论
  • 147 次浏览
  • A+
所属分类:.NET技术
摘要

AspectCore 在注册服务这块比较简单,默认是无法根据Name去注册和解析对象,这边做一下这块的扩展

AspectCore 在注册服务这块比较简单,默认是无法根据Name去注册和解析对象,这边做一下这块的扩展

大致原理是根据自定义Name去生成对应的动态类型,然后使用委托或者对象的方式,进行注册

tips:由于底层原理的原因,无法支持Type的方式进行注册

 

定义好动态类型的接口,以及相关实现

 1 public interface INamedService : IDisposable  2 {  3     object Service { get; }  4 }  5   6 public interface INamedService<out T> : INamedService  7     where T : class  8 {  9     new T Service { get; } 10 } 11  12 public interface INamedService<out TService, TNamed> : INamedService<TService> 13     where TService : class 14     where TNamed : struct 15 { 16 } 17  18 internal class NamedService<TService, TNamed> : INamedService<TService, TNamed> 19     where TService : class 20     where TNamed : struct 21 { 22     ~NamedService() 23     { 24         Dispose(false); 25     } 26  27     public NamedService(TService service) 28     { 29         Service = service; 30     } 31  32     public TService Service { get; private set; } 33  34     object INamedService.Service => Service; 35  36     public void Dispose() 37     { 38         Dispose(true); 39         GC.SuppressFinalize(this); 40     } 41  42     private void Dispose(bool disposing) 43     { 44         if (!disposing) 45         { 46             return; 47         } 48  49         if (Service == null) 50         { 51             return; 52         } 53  54         if (Service is IDisposable disposable) 55         { 56             disposable.Dispose(); 57             Service = null; 58         } 59     } 60 }

 

根据自定义Name和ServiceType生成对应的动态类型

 1 public static class NamedBuilder  2 {  3     private const string KeyPrefix = "Ksd.NamedType.";  4     private static readonly ModuleBuilder _moduleBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Ksd.DynamicAssembly.NamedType"), AssemblyBuilderAccess.Run).DefineDynamicModule("NamedTypeModule");  5     private static readonly ConcurrentDictionary<string, Type> _namedTypes = new(StringComparer.OrdinalIgnoreCase);  6   7     private static Type GetNamedType(string name)  8     {  9         if (name.IsNull()) 10         { 11             throw new ArgumentNullException(nameof(name)); 12         } 13  14         name = KeyPrefix + name; 15  16         return _namedTypes.GetOrAdd(name, k => 17         { 18             var tb = _moduleBuilder.DefineType(k, TypeAttributes.Public | TypeAttributes.Sealed, typeof(ValueType)); 19             var type = tb.CreateTypeInfo().AsType(); 20             return type; 21         }); 22     } 23  24     public static Type CreateServiceType(string name, Type serviceType) 25     { 26         var namedType = GetNamedType(name); 27         return typeof(NamedService<,>).MakeGenericType(serviceType, namedType); 28     } 29  30     public static Type CreateServiceBaseType(string name, Type serviceType) 31     { 32         var namedType = GetNamedType(name); 33         return typeof(INamedService<,>).MakeGenericType(serviceType, namedType); 34     } 35  36     public static Type GetNameServiceBaseType(Type namedType) 37     { 38         return namedType.GetInterfaces()[0]; 39     } 40 }

 

封装根据自定义的Name注册和解析的相关方法

  1 public static class NamedServiceExtensions   2 {   3     #region AddInstance   4     public static IServiceContext AddInstance(this IServiceContext services, Type serviceType, object implementationInstance, string name)   5     {   6         if (name.IsNull())   7         {   8             return services.AddInstance(serviceType, implementationInstance);   9         }  10   11         if (services == null)  12         {  13             throw new ArgumentNullException(nameof(services));  14         }  15   16         if (serviceType == null)  17         {  18             throw new ArgumentNullException(nameof(serviceType));  19         }  20   21         if (implementationInstance == null)  22         {  23             throw new ArgumentNullException(nameof(implementationInstance));  24         }  25   26         var namedType = NamedBuilder.CreateServiceType(name, serviceType);  27         services.AddInstance(NamedBuilder.GetNameServiceBaseType(namedType), Activator.CreateInstance(namedType, implementationInstance));  28         return services;  29     }  30   31     public static IServiceContext AddInstance<TService>(this IServiceContext services, TService implementationInstance, string name)  32     {  33         return services.AddInstance(typeof(TService), implementationInstance, name);  34     }  35     #endregion  36   37     #region AddDelegate  38     public static IServiceContext AddDelegate(this IServiceContext services, Type serviceType, Func<IServiceResolver, object> implementationDelegate, string name, Lifetime lifetime = Lifetime.Transient)  39     {  40         if (name.IsNull())  41         {  42             return services.AddDelegate(serviceType, implementationDelegate, lifetime);  43         }  44   45         if (services == null)  46         {  47             throw new ArgumentNullException(nameof(services));  48         }  49   50         if (serviceType == null)  51         {  52             throw new ArgumentNullException(nameof(serviceType));  53         }  54   55         if (implementationDelegate == null)  56         {  57             throw new ArgumentNullException(nameof(implementationDelegate));  58         }  59   60         var namedType = NamedBuilder.CreateServiceType(name, serviceType);  61         services.AddDelegate(NamedBuilder.GetNameServiceBaseType(namedType), s => Activator.CreateInstance(namedType, implementationDelegate(s)), lifetime);  62         return services;  63     }  64   65     public static IServiceContext AddDelegate<TService>(this IServiceContext services, Func<IServiceResolver, TService> implementationDelegate, string name, Lifetime lifetime = Lifetime.Transient)  66         where TService : class  67     {  68         return services.AddDelegate(typeof(TService), implementationDelegate, name, lifetime);  69     }  70     #endregion  71   72     #region Resolve  73     public static T Resolve<T>(this IServiceResolver serviceResolver, string name)  74         where T : class  75     {  76         if (name.IsNull())  77         {  78             return serviceResolver.Resolve<T>();  79         }  80   81         var namedType = NamedBuilder.CreateServiceBaseType(name, typeof(T));  82         var namedService = serviceResolver.Resolve(namedType) as INamedService<T>;  83         return namedService?.Service;  84     }  85   86     public static object Resolve(this IServiceResolver serviceResolver, Type serviceType, string name)  87     {  88         if (name.IsNull())  89         {  90             return serviceResolver.Resolve(serviceType);  91         }  92   93         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType);  94         var namedService = serviceResolver.Resolve(namedType) as INamedService;  95         return namedService?.Service;  96     }  97   98     public static IEnumerable<T> ResolveMany<T>(this IServiceResolver serviceResolver, string name)  99         where T : class 100     { 101         if (name.IsNull()) 102         { 103             return serviceResolver.ResolveMany<T>(); 104         } 105  106         var namedType = NamedBuilder.CreateServiceBaseType(name, typeof(T)); 107         var namedServices = serviceResolver.ResolveMany(namedType).OfType<INamedService<T>>(); 108         return namedServices.Select(t => t.Service); 109     } 110  111     public static IEnumerable<object> ResolveMany(this IServiceResolver serviceResolver, Type serviceType, string name) 112     { 113         if (name.IsNull()) 114         { 115             return serviceResolver.ResolveMany(serviceType); 116         } 117  118         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType); 119         var namedServices = serviceResolver.ResolveMany(namedType) as IEnumerable<INamedService>; 120         return namedServices.Select(t => t.Service); 121     } 122     #endregion 123  124     #region Remove 125     public static IServiceContext RemoveAll(this IServiceContext services, Type serviceType, string name) 126     { 127         if (name.IsNull()) 128         { 129             return services.RemoveAll(serviceType); 130         } 131  132         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType); 133         services.RemoveAll(namedType); 134         return services; 135     } 136  137     public static IServiceContext RemoveAll<T>(this IServiceContext services, string name) 138         where T : class 139     { 140         return services.RemoveAll(typeof(T), name); 141     } 142     #endregion 143  144     #region Other 145     public static bool Contains(this IServiceContext services, Type serviceType, string name) 146     { 147         if (name.IsNull()) 148         { 149             return services.Contains(serviceType); 150         } 151  152         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType); 153         return services.Contains(namedType); 154     } 155     #endregion 156 }

 

根据以上原理,MSDI亦可作对应的注册以及解析方法

  1 public static class NamedServiceExtensions   2 {   3     #region Add   4     public static IServiceCollection AddSingleton(this IServiceCollection services, Type serviceType, object implementationInstance, string name)   5     {   6         services.AddNamed(serviceType, _ => implementationInstance, name, ServiceLifetime.Singleton);   7         return services;   8     }   9   10     public static IServiceCollection AddSingleton<TService>(this IServiceCollection services, TService implementationInstance, string name)  11         where TService : class  12     {  13         return services.AddSingleton(typeof(TService), implementationInstance, name);  14     }  15   16     public static IServiceCollection AddSingleton(this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory, string name)  17     {  18         services.AddNamed(serviceType, implementationFactory, name, ServiceLifetime.Singleton);  19         return services;  20     }  21   22     public static IServiceCollection AddSingleton<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory, string name)  23         where TService : class  24     {  25         return services.AddSingleton(typeof(TService), implementationFactory, name);  26     }  27   28     public static IServiceCollection AddScoped(this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory, string name)  29     {  30         services.AddNamed(serviceType, implementationFactory, name, ServiceLifetime.Scoped);  31         return services;  32     }  33   34     public static IServiceCollection AddScoped<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory, string name)  35         where TService : class  36     {  37         return services.AddScoped(typeof(TService), implementationFactory, name);  38     }  39   40     public static IServiceCollection AddTransient(this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory, string name)  41     {  42         services.AddNamed(serviceType, implementationFactory, name, ServiceLifetime.Transient);  43         return services;  44     }  45   46     public static IServiceCollection AddTransient<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory, string name)  47         where TService : class  48     {  49         return services.AddTransient(typeof(TService), implementationFactory, name);  50     }  51   52     public static IServiceCollection AddNamed(this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory, string name, ServiceLifetime lifetime = ServiceLifetime.Transient)  53     {  54         if (name.IsNull())  55         {  56             services.Add(ServiceDescriptor.Describe(serviceType, implementationFactory, lifetime));  57             return services;  58         }  59   60         if (services == null)  61         {  62             throw new ArgumentNullException(nameof(services));  63         }  64   65         if (serviceType == null)  66         {  67             throw new ArgumentNullException(nameof(serviceType));  68         }  69   70         if (implementationFactory == null)  71         {  72             throw new ArgumentNullException(nameof(implementationFactory));  73         }  74   75         var namedType = NamedBuilder.CreateServiceType(name, serviceType);  76   77         services.Add(ServiceDescriptor.Describe(namedType, s => Activator.CreateInstance(namedType, implementationFactory(s)), lifetime));  78         return services;  79     }  80     #endregion  81   82     #region GetService  83     public static T GetService<T>(this IServiceProvider serviceProvider, string name)  84         where T : class  85     {  86         if (serviceProvider == null)  87         {  88             throw new ArgumentNullException(nameof(serviceProvider));  89         }  90   91         if (name.IsNull())  92         {  93             return serviceProvider.GetService<T>();  94         }  95   96         var namedType = NamedBuilder.CreateServiceBaseType(name, typeof(T));  97         var namedService = serviceProvider.GetService(namedType) as INamedService<T>;  98         return namedService?.Service;  99     } 100  101     public static object GetService(this IServiceProvider serviceProvider, Type serviceType, string name) 102     { 103         if (serviceProvider == null) 104         { 105             throw new ArgumentNullException(nameof(serviceProvider)); 106         } 107  108         if (name.IsNull()) 109         { 110             return serviceProvider.GetService(serviceType); 111         } 112  113         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType); 114         var namedService = serviceProvider.GetService(namedType) as INamedService; 115         return namedService?.Service; 116     } 117  118     public static IEnumerable<T> GetServices<T>(this IServiceProvider serviceProvider, string name) 119         where T : class 120     { 121         if (serviceProvider == null) 122         { 123             throw new ArgumentNullException(nameof(serviceProvider)); 124         } 125  126         if (name.IsNull()) 127         { 128             return serviceProvider.GetServices<T>(); 129         } 130  131         var namedType = NamedBuilder.CreateServiceBaseType(name, typeof(T)); 132         var namedServices = serviceProvider.GetServices(namedType) as IEnumerable<INamedService<T>>; 133         return namedServices.Select(t => t.Service); 134     } 135  136     public static IEnumerable<object> GetServices(this IServiceProvider serviceProvider, Type serviceType, string name) 137     { 138         if (serviceProvider == null) 139         { 140             throw new ArgumentNullException(nameof(serviceProvider)); 141         } 142  143         if (name.IsNull()) 144         { 145             return serviceProvider.GetServices(serviceType); 146         } 147  148         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType); 149         var namedServices = serviceProvider.GetServices(namedType) as IEnumerable<INamedService>; 150         return namedServices.Select(t => t.Service); 151     } 152     #endregion 153  154     #region Remove 155     public static IServiceCollection RemoveAll(this IServiceCollection services, Type serviceType, string name) 156     { 157         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType); 158         services.RemoveAll(namedType); 159         return services; 160     } 161  162     public static IServiceCollection RemoveAll<T>(this IServiceCollection services, string name) 163     { 164         return services.RemoveAll(typeof(T), name); 165     } 166     #endregion 167  168     #region Other 169     public static bool Contains(this IServiceCollection services, Type serviceType, string name) 170     { 171         if (name.IsNull()) 172         { 173             return services.Contains(serviceType); 174         } 175  176         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType); 177         return services.Contains(namedType); 178     } 179     #endregion 180 }