0
AspectCore和MSDI 实现Name注册以及解析对象 - 火__舞
source link: https://www.cnblogs.com/jsnaner/p/17347050.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
AspectCore和MSDI 实现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 }
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK