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 }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |