找回密码
 立即注册
首页 资源区 代码 c# 批量注入示例代码

c# 批量注入示例代码

左丘纨 2025-5-29 10:54:02
  1. using Microsoft.Extensions.DependencyInjection;
  2. using System;
  3. using System.Linq;
  4. using System.Reflection;
  5. // 自定义属性来标记服务类型
  6. [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
  7. public class ServiceTypeAttribute : Attribute
  8. {
  9.     public ServiceLifetime Lifetime { get; }
  10.     public ServiceTypeAttribute(ServiceLifetime lifetime)
  11.     {
  12.         Lifetime = lifetime;
  13.     }
  14. }
  15. public static class DependencyInjectionExtensions
  16. {
  17.     /// <summary>
  18.     /// 批量注册服务
  19.     /// </summary>
  20.     /// <param name="services">IServiceCollection</param>
  21.     /// <param name="servicePrefix">服务类的前缀,例如 "Service"</param>
  22.     /// <param name="interfacePrefix">接口的前缀,例如 "I"</param>
  23.     public static void RegisterServices(this IServiceCollection services, string servicePrefix, string interfacePrefix)
  24.     {
  25.         if (services == null)
  26.         {
  27.             throw new ArgumentNullException(nameof(services));
  28.         }
  29.         // 获取当前程序集中所有类
  30.         var types = Assembly.GetExecutingAssembly().GetTypes();
  31.         // 筛选出符合服务命名约定的类
  32.         var serviceTypes = types
  33.             .Where(t => t.Name.StartsWith(servicePrefix) && !t.IsInterface && !t.IsAbstract)
  34.             .ToList();
  35.         // 遍历所有服务类
  36.         foreach (var serviceType in serviceTypes)
  37.         {
  38.             // 尝试查找对应的接口
  39.             var interfaceType = types.FirstOrDefault(t => t.Name == interfacePrefix + serviceType.Name.Substring(servicePrefix.Length) && t.IsInterface);
  40.             if (interfaceType != null)
  41.             {
  42.                 // 获取服务类型上的 ServiceTypeAttribute
  43.                 var serviceTypeAttribute = serviceType.GetCustomAttribute<ServiceTypeAttribute>();
  44.                 var lifetime = serviceTypeAttribute?.Lifetime ?? ServiceLifetime.Scoped; // 默认使用 Scoped
  45.                 // 根据不同的生命周期注册服务
  46.                 switch (lifetime)
  47.                 {
  48.                     case ServiceLifetime.Singleton:
  49.                         services.AddSingleton(interfaceType, serviceType);
  50.                         break;
  51.                     case ServiceLifetime.Scoped:
  52.                         services.AddScoped(interfaceType, serviceType);
  53.                         break;
  54.                     case ServiceLifetime.Transient:
  55.                         services.AddTransient(interfaceType, serviceType);
  56.                         break;
  57.                     default:
  58.                         services.AddScoped(interfaceType, serviceType); // 默认使用 Scoped
  59.                         break;
  60.                 }
  61.             }
  62.             else
  63.             {
  64.                 // 如果没有找到对应的接口,则可以选择只注册服务本身,或者抛出异常
  65.                 // 这里选择抛出异常,提示开发者需要有对应的接口
  66.                 throw new InvalidOperationException($"Service {serviceType.Name} does not have a corresponding interface (expected interface name: {interfacePrefix}{serviceType.Name.Substring(servicePrefix.Length)})");
  67.             }
  68.         }
  69.     }
  70. }
  71. // 示例接口和服务
  72. public interface IUserService
  73. {
  74.     void DoSomething();
  75. }
  76. [ServiceType(ServiceLifetime.Scoped)] // 使用属性标记生命周期
  77. public class UserService : IUserService
  78. {
  79.     public void DoSomething()
  80.     {
  81.         Console.WriteLine("UserService.DoSomething() called.");
  82.     }
  83. }
  84. public interface IOrderService
  85. {
  86.      void ProcessOrder();
  87. }
  88. [ServiceType(ServiceLifetime.Transient)]
  89. public class OrderService: IOrderService
  90. {
  91.     public void ProcessOrder()
  92.     {
  93.         Console.WriteLine("OrderService.ProcessOrder() called.");
  94.     }
  95. }
  96. public class Program
  97. {
  98.     public static void Main(string[] args)
  99.     {
  100.         // 创建 ServiceCollection
  101.         IServiceCollection services = new ServiceCollection();
  102.         // 注册服务
  103.         services.RegisterServices("Service", "I");
  104.         // 添加其他必要的服务,例如 MVC
  105.         services.AddMvc(); // 如果是 ASP.NET Core MVC 项目
  106.         // 构建 ServiceProvider
  107.         IServiceProvider serviceProvider = services.BuildServiceProvider();
  108.         // 从 ServiceProvider 中获取服务并使用
  109.         var userService = serviceProvider.GetService<IUserService>();
  110.         userService?.DoSomething();
  111.         var orderService = serviceProvider.GetService<IOrderService>();
  112.         orderService?.ProcessOrder();
  113.         Console.ReadKey();
  114.     }
  115. }
复制代码
代码说明

  • ServiceTypeAttribute: 这是一个自定义属性,用于显式指定服务类的生命周期(Singleton、Scoped 或 Transient)。
  • RegisterServices 扩展方法:

    • 它扩展了 IServiceCollection,提供了一个便捷的方法来批量注册服务。
    • servicePrefix 参数指定服务类的前缀(例如,"Service")。
    • interfacePrefix 参数指定接口的前缀(例如,"I")。
    • 它使用反射来查找程序集中所有符合命名约定的类(例如,以 "Service" 开头的类)。
    • 它假定接口的命名约定是接口前缀 + 服务类名(去掉服务前缀)。 例如,如果服务类是 UserService,则对应的接口应该是 IUserService。
    • 它使用 GetCustomAttribute 方法获取服务类上的 ServiceTypeAttribute 属性,并根据属性中指定的生命周期注册服务。 如果未找到此属性,则默认使用 Scoped 生命周期。
    • 如果找不到与服务类对应的接口,它会抛出一个异常,指示缺少必需的接口。

  • 示例:

    • IUserService 和 UserService 演示了如何定义一个服务及其接口。
    • IOrderService 和 OrderService 演示了另一个服务及其接口,并使用[ServiceType] 特性标记了生命周期
    • 在 Main 方法中,我们创建了一个 ServiceCollection,调用 RegisterServices 方法注册服务,然后从 ServiceProvider 中解析并使用这些服务。

使用说明

  • 定义您的服务接口和服务类,并确保它们遵循命名约定(例如,IUserService 和 UserService)。
  • 使用 ServiceTypeAttribute 属性标记您的服务类,以指定其生命周期。 如果省略此属性,则默认使用 Scoped 生命周期。
  • 在您的应用程序的启动配置中(例如,Main 方法或 ConfigureServices 方法中),获取 IServiceCollection 的实例,并调用 RegisterServices 扩展方法,传递服务类前缀和接口前缀。
  • 像往常一样使用依赖注入来获取服务实例。
这个方法提供了一种灵活且类型安全的方式来批量注册服务,并允许您通过属性显式控制每个服务的生命周期。
  

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册