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

2023-06-25,,

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 }

AspectCore和MSDI 实现Name注册以及解析对象的相关教程结束。

《AspectCore和MSDI 实现Name注册以及解析对象.doc》

下载本文的Word格式文档,以方便收藏与打印。