AspectCore 在註冊服務這塊比較簡單,預設是無法根據Name去註冊和解析對象,這邊做一下這塊的擴展 大致原理是根據自定義Name去生成對應的動態類型,然後使用委托或者對象的方式,進行註冊 tips:由於底層原理的原因,無法支持Type的方式進行註冊 定義好動態類型的介面,以及相關實現 1 p ...
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(