AspectCore 在注册服务这块比较简单,默认是无法根据Name去注册和解析对象,这边做一下这块的扩展
大致原理是根据自定义Name去生成对应的动态类型,然后使用委托或者对象的方式,进行注册
tips:由于底层原理的原因,无法支持Type的方式进行注册
定义好动态类型的接口,以及相关实现
1 public interface INamedService : IDisposable2 {3 object Service { get; }4 }5 6 public interface INamedService<out T> : INamedService7 where T : class8 {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 NamedBuilder2 {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 NamedServiceExtensions2 {3 #region AddInstance4 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 #endregion36 37 #region AddDelegate38 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 : class67 {68 return services.AddDelegate(typeof(TService), implementationDelegate, name, lifetime);69 }70 #endregion71 72 #region Resolve73 public static T Resolve<T>(this IServiceResolver serviceResolver, string name)74 where T : class75 {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 NamedServiceExtensions2 {3 #region Add4 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 : class12 {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 : class24 {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 : class36 {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 : class48 {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 #endregion81 82 #region GetService83 public static T GetService<T>(this IServiceProvider serviceProvider, string name)84 where T : class85 {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 }