翼度科技»论坛 编程开发 .net 查看内容

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

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
AspectCore 在注册服务这块比较简单,默认是无法根据Name去注册和解析对象,这边做一下这块的扩展
大致原理是根据自定义Name去生成对应的动态类型,然后使用委托或者对象的方式,进行注册
tips:由于底层原理的原因,无法支持Type的方式进行注册
 
定义好动态类型的接口,以及相关实现
  1. 1 public interface INamedService : IDisposable
  2. 2 {
  3. 3     object Service { get; }
  4. 4 }
  5. 5
  6. 6 public interface INamedService<out T> : INamedService
  7. 7     where T : class
  8. 8 {
  9. 9     new T Service { get; }
  10. 10 }
  11. 11
  12. 12 public interface INamedService<out TService, TNamed> : INamedService<TService>
  13. 13     where TService : class
  14. 14     where TNamed : struct
  15. 15 {
  16. 16 }
  17. 17
  18. 18 internal class NamedService<TService, TNamed> : INamedService<TService, TNamed>
  19. 19     where TService : class
  20. 20     where TNamed : struct
  21. 21 {
  22. 22     ~NamedService()
  23. 23     {
  24. 24         Dispose(false);
  25. 25     }
  26. 26
  27. 27     public NamedService(TService service)
  28. 28     {
  29. 29         Service = service;
  30. 30     }
  31. 31
  32. 32     public TService Service { get; private set; }
  33. 33
  34. 34     object INamedService.Service => Service;
  35. 35
  36. 36     public void Dispose()
  37. 37     {
  38. 38         Dispose(true);
  39. 39         GC.SuppressFinalize(this);
  40. 40     }
  41. 41
  42. 42     private void Dispose(bool disposing)
  43. 43     {
  44. 44         if (!disposing)
  45. 45         {
  46. 46             return;
  47. 47         }
  48. 48
  49. 49         if (Service == null)
  50. 50         {
  51. 51             return;
  52. 52         }
  53. 53
  54. 54         if (Service is IDisposable disposable)
  55. 55         {
  56. 56             disposable.Dispose();
  57. 57             Service = null;
  58. 58         }
  59. 59     }
  60. 60 }
复制代码
 
根据自定义Name和ServiceType生成对应的动态类型
  1. 1 public static class NamedBuilder
  2. 2 {
  3. 3     private const string KeyPrefix = "Ksd.NamedType.";
  4. 4     private static readonly ModuleBuilder _moduleBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Ksd.DynamicAssembly.NamedType"), AssemblyBuilderAccess.Run).DefineDynamicModule("NamedTypeModule");
  5. 5     private static readonly ConcurrentDictionary<string, Type> _namedTypes = new(StringComparer.OrdinalIgnoreCase);
  6. 6
  7. 7     private static Type GetNamedType(string name)
  8. 8     {
  9. 9         if (name.IsNull())
  10. 10         {
  11. 11             throw new ArgumentNullException(nameof(name));
  12. 12         }
  13. 13
  14. 14         name = KeyPrefix + name;
  15. 15
  16. 16         return _namedTypes.GetOrAdd(name, k =>
  17. 17         {
  18. 18             var tb = _moduleBuilder.DefineType(k, TypeAttributes.Public | TypeAttributes.Sealed, typeof(ValueType));
  19. 19             var type = tb.CreateTypeInfo().AsType();
  20. 20             return type;
  21. 21         });
  22. 22     }
  23. 23
  24. 24     public static Type CreateServiceType(string name, Type serviceType)
  25. 25     {
  26. 26         var namedType = GetNamedType(name);
  27. 27         return typeof(NamedService<,>).MakeGenericType(serviceType, namedType);
  28. 28     }
  29. 29
  30. 30     public static Type CreateServiceBaseType(string name, Type serviceType)
  31. 31     {
  32. 32         var namedType = GetNamedType(name);
  33. 33         return typeof(INamedService<,>).MakeGenericType(serviceType, namedType);
  34. 34     }
  35. 35
  36. 36     public static Type GetNameServiceBaseType(Type namedType)
  37. 37     {
  38. 38         return namedType.GetInterfaces()[0];
  39. 39     }
  40. 40 }
复制代码
 
封装根据自定义的Name注册和解析的相关方法
  1.   1 public static class NamedServiceExtensions
  2.   2 {
  3.   3     #region AddInstance
  4.   4     public static IServiceContext AddInstance(this IServiceContext services, Type serviceType, object implementationInstance, string name)
  5.   5     {
  6.   6         if (name.IsNull())
  7.   7         {
  8.   8             return services.AddInstance(serviceType, implementationInstance);
  9.   9         }
  10. 10
  11. 11         if (services == null)
  12. 12         {
  13. 13             throw new ArgumentNullException(nameof(services));
  14. 14         }
  15. 15
  16. 16         if (serviceType == null)
  17. 17         {
  18. 18             throw new ArgumentNullException(nameof(serviceType));
  19. 19         }
  20. 20
  21. 21         if (implementationInstance == null)
  22. 22         {
  23. 23             throw new ArgumentNullException(nameof(implementationInstance));
  24. 24         }
  25. 25
  26. 26         var namedType = NamedBuilder.CreateServiceType(name, serviceType);
  27. 27         services.AddInstance(NamedBuilder.GetNameServiceBaseType(namedType), Activator.CreateInstance(namedType, implementationInstance));
  28. 28         return services;
  29. 29     }
  30. 30
  31. 31     public static IServiceContext AddInstance<TService>(this IServiceContext services, TService implementationInstance, string name)
  32. 32     {
  33. 33         return services.AddInstance(typeof(TService), implementationInstance, name);
  34. 34     }
  35. 35     #endregion
  36. 36
  37. 37     #region AddDelegate
  38. 38     public static IServiceContext AddDelegate(this IServiceContext services, Type serviceType, Func<IServiceResolver, object> implementationDelegate, string name, Lifetime lifetime = Lifetime.Transient)
  39. 39     {
  40. 40         if (name.IsNull())
  41. 41         {
  42. 42             return services.AddDelegate(serviceType, implementationDelegate, lifetime);
  43. 43         }
  44. 44
  45. 45         if (services == null)
  46. 46         {
  47. 47             throw new ArgumentNullException(nameof(services));
  48. 48         }
  49. 49
  50. 50         if (serviceType == null)
  51. 51         {
  52. 52             throw new ArgumentNullException(nameof(serviceType));
  53. 53         }
  54. 54
  55. 55         if (implementationDelegate == null)
  56. 56         {
  57. 57             throw new ArgumentNullException(nameof(implementationDelegate));
  58. 58         }
  59. 59
  60. 60         var namedType = NamedBuilder.CreateServiceType(name, serviceType);
  61. 61         services.AddDelegate(NamedBuilder.GetNameServiceBaseType(namedType), s => Activator.CreateInstance(namedType, implementationDelegate(s)), lifetime);
  62. 62         return services;
  63. 63     }
  64. 64
  65. 65     public static IServiceContext AddDelegate<TService>(this IServiceContext services, Func<IServiceResolver, TService> implementationDelegate, string name, Lifetime lifetime = Lifetime.Transient)
  66. 66         where TService : class
  67. 67     {
  68. 68         return services.AddDelegate(typeof(TService), implementationDelegate, name, lifetime);
  69. 69     }
  70. 70     #endregion
  71. 71
  72. 72     #region Resolve
  73. 73     public static T Resolve<T>(this IServiceResolver serviceResolver, string name)
  74. 74         where T : class
  75. 75     {
  76. 76         if (name.IsNull())
  77. 77         {
  78. 78             return serviceResolver.Resolve<T>();
  79. 79         }
  80. 80
  81. 81         var namedType = NamedBuilder.CreateServiceBaseType(name, typeof(T));
  82. 82         var namedService = serviceResolver.Resolve(namedType) as INamedService<T>;
  83. 83         return namedService?.Service;
  84. 84     }
  85. 85
  86. 86     public static object Resolve(this IServiceResolver serviceResolver, Type serviceType, string name)
  87. 87     {
  88. 88         if (name.IsNull())
  89. 89         {
  90. 90             return serviceResolver.Resolve(serviceType);
  91. 91         }
  92. 92
  93. 93         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType);
  94. 94         var namedService = serviceResolver.Resolve(namedType) as INamedService;
  95. 95         return namedService?.Service;
  96. 96     }
  97. 97
  98. 98     public static IEnumerable<T> ResolveMany<T>(this IServiceResolver serviceResolver, string name)
  99. 99         where T : class
  100. 100     {
  101. 101         if (name.IsNull())
  102. 102         {
  103. 103             return serviceResolver.ResolveMany<T>();
  104. 104         }
  105. 105
  106. 106         var namedType = NamedBuilder.CreateServiceBaseType(name, typeof(T));
  107. 107         var namedServices = serviceResolver.ResolveMany(namedType).OfType<INamedService<T>>();
  108. 108         return namedServices.Select(t => t.Service);
  109. 109     }
  110. 110
  111. 111     public static IEnumerable<object> ResolveMany(this IServiceResolver serviceResolver, Type serviceType, string name)
  112. 112     {
  113. 113         if (name.IsNull())
  114. 114         {
  115. 115             return serviceResolver.ResolveMany(serviceType);
  116. 116         }
  117. 117
  118. 118         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType);
  119. 119         var namedServices = serviceResolver.ResolveMany(namedType) as IEnumerable<INamedService>;
  120. 120         return namedServices.Select(t => t.Service);
  121. 121     }
  122. 122     #endregion
  123. 123
  124. 124     #region Remove
  125. 125     public static IServiceContext RemoveAll(this IServiceContext services, Type serviceType, string name)
  126. 126     {
  127. 127         if (name.IsNull())
  128. 128         {
  129. 129             return services.RemoveAll(serviceType);
  130. 130         }
  131. 131
  132. 132         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType);
  133. 133         services.RemoveAll(namedType);
  134. 134         return services;
  135. 135     }
  136. 136
  137. 137     public static IServiceContext RemoveAll<T>(this IServiceContext services, string name)
  138. 138         where T : class
  139. 139     {
  140. 140         return services.RemoveAll(typeof(T), name);
  141. 141     }
  142. 142     #endregion
  143. 143
  144. 144     #region Other
  145. 145     public static bool Contains(this IServiceContext services, Type serviceType, string name)
  146. 146     {
  147. 147         if (name.IsNull())
  148. 148         {
  149. 149             return services.Contains(serviceType);
  150. 150         }
  151. 151
  152. 152         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType);
  153. 153         return services.Contains(namedType);
  154. 154     }
  155. 155     #endregion
  156. 156 }
复制代码
 
根据以上原理,MSDI亦可作对应的注册以及解析方法
  1.   1 public static class NamedServiceExtensions
  2.   2 {
  3.   3     #region Add
  4.   4     public static IServiceCollection AddSingleton(this IServiceCollection services, Type serviceType, object implementationInstance, string name)
  5.   5     {
  6.   6         services.AddNamed(serviceType, _ => implementationInstance, name, ServiceLifetime.Singleton);
  7.   7         return services;
  8.   8     }
  9.   9
  10. 10     public static IServiceCollection AddSingleton<TService>(this IServiceCollection services, TService implementationInstance, string name)
  11. 11         where TService : class
  12. 12     {
  13. 13         return services.AddSingleton(typeof(TService), implementationInstance, name);
  14. 14     }
  15. 15
  16. 16     public static IServiceCollection AddSingleton(this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory, string name)
  17. 17     {
  18. 18         services.AddNamed(serviceType, implementationFactory, name, ServiceLifetime.Singleton);
  19. 19         return services;
  20. 20     }
  21. 21
  22. 22     public static IServiceCollection AddSingleton<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory, string name)
  23. 23         where TService : class
  24. 24     {
  25. 25         return services.AddSingleton(typeof(TService), implementationFactory, name);
  26. 26     }
  27. 27
  28. 28     public static IServiceCollection AddScoped(this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory, string name)
  29. 29     {
  30. 30         services.AddNamed(serviceType, implementationFactory, name, ServiceLifetime.Scoped);
  31. 31         return services;
  32. 32     }
  33. 33
  34. 34     public static IServiceCollection AddScoped<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory, string name)
  35. 35         where TService : class
  36. 36     {
  37. 37         return services.AddScoped(typeof(TService), implementationFactory, name);
  38. 38     }
  39. 39
  40. 40     public static IServiceCollection AddTransient(this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory, string name)
  41. 41     {
  42. 42         services.AddNamed(serviceType, implementationFactory, name, ServiceLifetime.Transient);
  43. 43         return services;
  44. 44     }
  45. 45
  46. 46     public static IServiceCollection AddTransient<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory, string name)
  47. 47         where TService : class
  48. 48     {
  49. 49         return services.AddTransient(typeof(TService), implementationFactory, name);
  50. 50     }
  51. 51
  52. 52     public static IServiceCollection AddNamed(this IServiceCollection services, Type serviceType, Func<IServiceProvider, object> implementationFactory, string name, ServiceLifetime lifetime = ServiceLifetime.Transient)
  53. 53     {
  54. 54         if (name.IsNull())
  55. 55         {
  56. 56             services.Add(ServiceDescriptor.Describe(serviceType, implementationFactory, lifetime));
  57. 57             return services;
  58. 58         }
  59. 59
  60. 60         if (services == null)
  61. 61         {
  62. 62             throw new ArgumentNullException(nameof(services));
  63. 63         }
  64. 64
  65. 65         if (serviceType == null)
  66. 66         {
  67. 67             throw new ArgumentNullException(nameof(serviceType));
  68. 68         }
  69. 69
  70. 70         if (implementationFactory == null)
  71. 71         {
  72. 72             throw new ArgumentNullException(nameof(implementationFactory));
  73. 73         }
  74. 74
  75. 75         var namedType = NamedBuilder.CreateServiceType(name, serviceType);
  76. 76
  77. 77         services.Add(ServiceDescriptor.Describe(namedType, s => Activator.CreateInstance(namedType, implementationFactory(s)), lifetime));
  78. 78         return services;
  79. 79     }
  80. 80     #endregion
  81. 81
  82. 82     #region GetService
  83. 83     public static T GetService<T>(this IServiceProvider serviceProvider, string name)
  84. 84         where T : class
  85. 85     {
  86. 86         if (serviceProvider == null)
  87. 87         {
  88. 88             throw new ArgumentNullException(nameof(serviceProvider));
  89. 89         }
  90. 90
  91. 91         if (name.IsNull())
  92. 92         {
  93. 93             return serviceProvider.GetService<T>();
  94. 94         }
  95. 95
  96. 96         var namedType = NamedBuilder.CreateServiceBaseType(name, typeof(T));
  97. 97         var namedService = serviceProvider.GetService(namedType) as INamedService<T>;
  98. 98         return namedService?.Service;
  99. 99     }
  100. 100
  101. 101     public static object GetService(this IServiceProvider serviceProvider, Type serviceType, string name)
  102. 102     {
  103. 103         if (serviceProvider == null)
  104. 104         {
  105. 105             throw new ArgumentNullException(nameof(serviceProvider));
  106. 106         }
  107. 107
  108. 108         if (name.IsNull())
  109. 109         {
  110. 110             return serviceProvider.GetService(serviceType);
  111. 111         }
  112. 112
  113. 113         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType);
  114. 114         var namedService = serviceProvider.GetService(namedType) as INamedService;
  115. 115         return namedService?.Service;
  116. 116     }
  117. 117
  118. 118     public static IEnumerable<T> GetServices<T>(this IServiceProvider serviceProvider, string name)
  119. 119         where T : class
  120. 120     {
  121. 121         if (serviceProvider == null)
  122. 122         {
  123. 123             throw new ArgumentNullException(nameof(serviceProvider));
  124. 124         }
  125. 125
  126. 126         if (name.IsNull())
  127. 127         {
  128. 128             return serviceProvider.GetServices<T>();
  129. 129         }
  130. 130
  131. 131         var namedType = NamedBuilder.CreateServiceBaseType(name, typeof(T));
  132. 132         var namedServices = serviceProvider.GetServices(namedType) as IEnumerable<INamedService<T>>;
  133. 133         return namedServices.Select(t => t.Service);
  134. 134     }
  135. 135
  136. 136     public static IEnumerable<object> GetServices(this IServiceProvider serviceProvider, Type serviceType, string name)
  137. 137     {
  138. 138         if (serviceProvider == null)
  139. 139         {
  140. 140             throw new ArgumentNullException(nameof(serviceProvider));
  141. 141         }
  142. 142
  143. 143         if (name.IsNull())
  144. 144         {
  145. 145             return serviceProvider.GetServices(serviceType);
  146. 146         }
  147. 147
  148. 148         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType);
  149. 149         var namedServices = serviceProvider.GetServices(namedType) as IEnumerable<INamedService>;
  150. 150         return namedServices.Select(t => t.Service);
  151. 151     }
  152. 152     #endregion
  153. 153
  154. 154     #region Remove
  155. 155     public static IServiceCollection RemoveAll(this IServiceCollection services, Type serviceType, string name)
  156. 156     {
  157. 157         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType);
  158. 158         services.RemoveAll(namedType);
  159. 159         return services;
  160. 160     }
  161. 161
  162. 162     public static IServiceCollection RemoveAll<T>(this IServiceCollection services, string name)
  163. 163     {
  164. 164         return services.RemoveAll(typeof(T), name);
  165. 165     }
  166. 166     #endregion
  167. 167
  168. 168     #region Other
  169. 169     public static bool Contains(this IServiceCollection services, Type serviceType, string name)
  170. 170     {
  171. 171         if (name.IsNull())
  172. 172         {
  173. 173             return services.Contains(serviceType);
  174. 174         }
  175. 175
  176. 176         var namedType = NamedBuilder.CreateServiceBaseType(name, serviceType);
  177. 177         return services.Contains(namedType);
  178. 178     }
  179. 179     #endregion
  180. 180 }
复制代码
 

来源:https://www.cnblogs.com/jsnaner/archive/2023/04/23/17347050.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具