ServiceCollectionExtensions.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. using Masuit.Tools.AspNetCore.ResumeFileResults.Executor;
  2. using Masuit.Tools.AspNetCore.ResumeFileResults.ResumeFileResult;
  3. using Masuit.Tools.Files;
  4. using Microsoft.AspNetCore.Mvc.Infrastructure;
  5. using Microsoft.Extensions.DependencyInjection.Extensions;
  6. using System.Reflection;
  7. using Masuit.Tools.Reflection;
  8. using Microsoft.Extensions.DependencyInjection;
  9. using Microsoft.Extensions.Hosting;
  10. namespace Masuit.Tools.Core.AspNetCore;
  11. /// <summary>
  12. /// 依赖注入ServiceCollection容器扩展方法
  13. /// </summary>
  14. public static class ServiceCollectionExtensions
  15. {
  16. /// <summary>
  17. /// 注入断点续传服务
  18. /// </summary>
  19. /// <param name="services"></param>
  20. /// <returns></returns>
  21. public static IServiceCollection AddResumeFileResult(this IServiceCollection services)
  22. {
  23. services.TryAddSingleton<IActionResultExecutor<ResumePhysicalFileResult>, ResumePhysicalFileResultExecutor>();
  24. services.TryAddSingleton<IActionResultExecutor<ResumeVirtualFileResult>, ResumeVirtualFileResultExecutor>();
  25. services.TryAddSingleton<IActionResultExecutor<ResumeFileStreamResult>, ResumeFileStreamResultExecutor>();
  26. services.TryAddSingleton<IActionResultExecutor<ResumeFileContentResult>, ResumeFileContentResultExecutor>();
  27. return services;
  28. }
  29. /// <summary>
  30. /// 注入7z压缩
  31. /// </summary>
  32. /// <param name="services"></param>
  33. /// <returns></returns>
  34. public static IServiceCollection AddSevenZipCompressor(this IServiceCollection services)
  35. {
  36. services.AddHttpClient<ISevenZipCompressor, SevenZipCompressor>();
  37. return services;
  38. }
  39. /// <summary>
  40. /// 自动扫描需要注册的服务,被ServiceInject标记的class可自动注入
  41. /// </summary>
  42. /// <param name="services"></param>
  43. public static void AutoRegisterServices(this IServiceCollection services)
  44. {
  45. var assemblies = AppDomain.CurrentDomain.GetAssemblies();
  46. services.RegisterServiceByAttribute(assemblies);
  47. services.RegisterBackgroundService(assemblies);
  48. }
  49. /// <summary>
  50. /// 自动扫描需要注册的服务,被ServiceInject标记的class可自动注入
  51. /// </summary>
  52. /// <param name="services"></param>
  53. /// <param name="assemblies"></param>
  54. public static void AutoRegisterServices(this IServiceCollection services, params Assembly[] assemblies)
  55. {
  56. services.RegisterServiceByAttribute(assemblies);
  57. services.RegisterBackgroundService(assemblies);
  58. }
  59. /// <summary>
  60. /// 通过 ServiceAttribute 批量注册服务
  61. /// </summary>
  62. /// <param name="services"></param>
  63. private static void RegisterServiceByAttribute(this IServiceCollection services, IEnumerable<Assembly> assemblies)
  64. {
  65. var types = assemblies.SelectMany(t => t.GetExportedTypes()).Where(t => (t.GetCustomAttributes(typeof(ServiceInjectAttribute), false).Length > 0 || t.GetInterfaces().Intersect([typeof(IScoped), typeof(ITransient), typeof(ISingleton)]).Any()) && t.IsClass && !t.IsAbstract);
  66. foreach (var type in types)
  67. {
  68. var typeInterface = type.GetInterfaces().Except([typeof(IScoped), typeof(ITransient), typeof(ISingleton)]).OrderBy(t => t.Name.HammingDistance(type.Name)).FirstOrDefault();
  69. if (typeInterface == null)
  70. {
  71. //服务非继承自接口的直接注入
  72. switch (type.GetCustomAttribute<ServiceInjectAttribute>()?.Lifetime)
  73. {
  74. case ServiceLifetime.Singleton:
  75. services.TryAddSingleton(type);
  76. break;
  77. case ServiceLifetime.Scoped:
  78. services.TryAddScoped(type);
  79. break;
  80. case ServiceLifetime.Transient:
  81. services.TryAddTransient(type);
  82. break;
  83. default:
  84. if (type.IsImplementsOf(typeof(IScoped)))
  85. {
  86. services.TryAddScoped(type);
  87. }
  88. else if (type.IsImplementsOf(typeof(ISingleton)))
  89. {
  90. services.TryAddSingleton(type);
  91. }
  92. else if (type.IsImplementsOf(typeof(ITransient)))
  93. {
  94. services.TryAddTransient(type);
  95. }
  96. break;
  97. }
  98. }
  99. else
  100. {
  101. //服务继承自接口的和接口一起注入
  102. switch (type.GetCustomAttribute<ServiceInjectAttribute>()?.Lifetime)
  103. {
  104. case ServiceLifetime.Singleton:
  105. services.TryAddSingleton(type);
  106. services.TryAddSingleton(typeInterface, type);
  107. break;
  108. case ServiceLifetime.Scoped:
  109. services.TryAddScoped(type);
  110. services.TryAddScoped(typeInterface, type);
  111. break;
  112. case ServiceLifetime.Transient:
  113. services.TryAddTransient(type);
  114. services.TryAddTransient(typeInterface, type);
  115. break;
  116. default:
  117. if (type.IsImplementsOf(typeof(IScoped)))
  118. {
  119. services.TryAddScoped(type);
  120. services.TryAddSingleton(typeInterface, type);
  121. }
  122. else if (type.IsImplementsOf(typeof(ISingleton)))
  123. {
  124. services.TryAddSingleton(type);
  125. services.TryAddSingleton(typeInterface, type);
  126. }
  127. else if (type.IsImplementsOf(typeof(ITransient)))
  128. {
  129. services.TryAddTransient(type);
  130. services.TryAddTransient(typeInterface, type);
  131. }
  132. break;
  133. }
  134. }
  135. }
  136. }
  137. /// <summary>
  138. /// 注册后台服务
  139. /// </summary>
  140. /// <param name="services"></param>
  141. private static void RegisterBackgroundService(this IServiceCollection services, IEnumerable<Assembly> assemblies)
  142. {
  143. var types = assemblies.SelectMany(t => t.GetTypes()).Where(t => typeof(BackgroundService).IsAssignableFrom(t) && !t.IsAbstract);
  144. foreach (var type in types)
  145. {
  146. services.TryAddSingleton(typeof(IHostedService), type);
  147. }
  148. }
  149. }
  150. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
  151. public class ServiceInjectAttribute : Attribute
  152. {
  153. public ServiceInjectAttribute()
  154. {
  155. }
  156. public ServiceInjectAttribute(ServiceLifetime lifetime)
  157. {
  158. Lifetime = lifetime;
  159. }
  160. public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Transient;
  161. }
  162. public interface IScoped;
  163. public interface ITransient;
  164. public interface ISingleton;