专业维修太阳能 發表於 2025-5-9 15:23:00

c# 批量注入示例代码

<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
using System.Reflection;

// 自定义属性来标记服务类型

public class ServiceTypeAttribute : Attribute
{
    public ServiceLifetime Lifetime { get; }

    public ServiceTypeAttribute(ServiceLifetime lifetime)
    {
      Lifetime = lifetime;
    }
}

public static class DependencyInjectionExtensions
{
    /// &lt;summary&gt;
    /// 批量注册服务
    /// &lt;/summary&gt;
    /// &lt;param name="services"&gt;IServiceCollection&lt;/param&gt;
    /// &lt;param name="servicePrefix"&gt;服务类的前缀,例如 "Service"&lt;/param&gt;
    /// &lt;param name="interfacePrefix"&gt;接口的前缀,例如 "I"&lt;/param&gt;
    public static void RegisterServices(this IServiceCollection services, string servicePrefix, string interfacePrefix)
    {
      if (services == null)
      {
            throw new ArgumentNullException(nameof(services));
      }

      // 获取当前程序集中所有类
      var types = Assembly.GetExecutingAssembly().GetTypes();

      // 筛选出符合服务命名约定的类
      var serviceTypes = types
            .Where(t =&gt; t.Name.StartsWith(servicePrefix) &amp;&amp; !t.IsInterface &amp;&amp; !t.IsAbstract)
            .ToList();

      // 遍历所有服务类
      foreach (var serviceType in serviceTypes)
      {
            // 尝试查找对应的接口
            var interfaceType = types.FirstOrDefault(t =&gt; t.Name == interfacePrefix + serviceType.Name.Substring(servicePrefix.Length) &amp;&amp; t.IsInterface);

            if (interfaceType != null)
            {
                // 获取服务类型上的 ServiceTypeAttribute
                var serviceTypeAttribute = serviceType.GetCustomAttribute&lt;ServiceTypeAttribute&gt;();
                var lifetime = serviceTypeAttribute?.Lifetime ?? ServiceLifetime.Scoped; // 默认使用 Scoped

                // 根据不同的生命周期注册服务
                switch (lifetime)
                {
                  case ServiceLifetime.Singleton:
                        services.AddSingleton(interfaceType, serviceType);
                        break;
                  case ServiceLifetime.Scoped:
                        services.AddScoped(interfaceType, serviceType);
                        break;
                  case ServiceLifetime.Transient:
                        services.AddTransient(interfaceType, serviceType);
                        break;
                  default:
                        services.AddScoped(interfaceType, serviceType); // 默认使用 Scoped
                        break;
                }
            }
            else
            {
                // 如果没有找到对应的接口,则可以选择只注册服务本身,或者抛出异常
                // 这里选择抛出异常,提示开发者需要有对应的接口
                throw new InvalidOperationException($"Service {serviceType.Name} does not have a corresponding interface (expected interface name: {interfacePrefix}{serviceType.Name.Substring(servicePrefix.Length)})");
            }
      }
    }
}

// 示例接口和服务
public interface IUserService
{
    void DoSomething();
}

// 使用属性标记生命周期
public class UserService : IUserService
{
    public void DoSomething()
    {
      Console.WriteLine("UserService.DoSomething() called.");
    }
}

public interface IOrderService
{
   void ProcessOrder();
}


public class OrderService: IOrderService
{
    public void ProcessOrder()
    {
      Console.WriteLine("OrderService.ProcessOrder() called.");
    }
}

public class Program
{
    public static void Main(string[] args)
    {
      // 创建 ServiceCollection
      IServiceCollection services = new ServiceCollection();

      // 注册服务
      services.RegisterServices("Service", "I");

      // 添加其他必要的服务,例如 MVC
      services.AddMvc(); // 如果是 ASP.NET Core MVC 项目

      // 构建 ServiceProvider
      IServiceProvider serviceProvider = services.BuildServiceProvider();

      // 从 ServiceProvider 中获取服务并使用
      var userService = serviceProvider.GetService&lt;IUserService&gt;();
      userService?.DoSomething();

      var orderService = serviceProvider.GetService&lt;IOrderService&gt;();
      orderService?.ProcessOrder();
      Console.ReadKey();
    }
}
</pre>
</div>
<p data-sourcepos="7:1-7:8"><strong>代码说明</strong></p>
<ol data-sourcepos="9:1-22:0">
<li data-sourcepos="9:1-9:86"><strong>ServiceTypeAttribute</strong>: 这是一个自定义属性,用于显式指定服务类的生命周期(Singleton、Scoped 或 Transient)。</li>
<li data-sourcepos="10:1-17:40"><strong>RegisterServices 扩展方法</strong>:
<ul data-sourcepos="11:5-17:40">
<li data-sourcepos="11:5-11:50">它扩展了 <code>IServiceCollection</code>,提供了一个便捷的方法来批量注册服务。</li>
<li data-sourcepos="12:5-12:49"><code>servicePrefix</code> 参数指定服务类的前缀(例如,<code>"Service"</code>)。</li>
<li data-sourcepos="13:5-13:44"><code>interfacePrefix</code> 参数指定接口的前缀(例如,<code>"I"</code>)。</li>
<li data-sourcepos="14:5-14:50">它使用反射来查找程序集中所有符合命名约定的类(例如,以 "Service" 开头的类)。</li>
<li data-sourcepos="15:5-15:87">它假定接口的命名约定是接口前缀 + 服务类名(去掉服务前缀)。 例如,如果服务类是 <code>UserService</code>,则对应的接口应该是 <code>IUserService</code>。</li>
<li data-sourcepos="16:5-16:116">它使用 <code>GetCustomAttribute</code> 方法获取服务类上的 <code>ServiceTypeAttribute</code> 属性,并根据属性中指定的生命周期注册服务。 如果未找到此属性,则默认使用 <code>Scoped</code> 生命周期。</li>
<li data-sourcepos="17:5-17:40">如果找不到与服务类对应的接口,它会抛出一个异常,指示缺少必需的接口。</li>
</ul>
</li>
<li data-sourcepos="18:1-22:0"><strong>示例</strong>:
<ul data-sourcepos="19:5-22:0">
<li data-sourcepos="19:5-19:53"><code>IUserService</code> 和 <code>UserService</code> 演示了如何定义一个服务及其接口。</li>
<li data-sourcepos="20:5-20:80"><code>IOrderService</code> 和 <code>OrderService</code> 演示了另一个服务及其接口,并使用<code></code> 特性标记了生命周期</li>
<li data-sourcepos="21:5-22:0">在 <code>Main</code> 方法中,我们创建了一个 <code>ServiceCollection</code>,调用 <code>RegisterServices</code> 方法注册服务,然后从 <code>ServiceProvider</code> 中解析并使用这些服务。</li>
</ul>
</li>
</ol>
<p data-sourcepos="23:1-23:8"><strong>使用说明</strong></p>
<ol data-sourcepos="25:1-29:0">
<li data-sourcepos="25:1-25:64">定义您的服务接口和服务类,并确保它们遵循命名约定(例如,<code>IUserService</code> 和 <code>UserService</code>)。</li>
<li data-sourcepos="26:1-26:79">使用 <code>ServiceTypeAttribute</code> 属性标记您的服务类,以指定其生命周期。 如果省略此属性,则默认使用 <code>Scoped</code> 生命周期。</li>
<li data-sourcepos="27:1-27:126">在您的应用程序的启动配置中(例如,<code>Main</code> 方法或 <code>ConfigureServices</code> 方法中),获取 <code>IServiceCollection</code> 的实例,并调用 <code>RegisterServices</code> 扩展方法,传递服务类前缀和接口前缀。</li>
<li data-sourcepos="28:1-29:0">像往常一样使用依赖注入来获取服务实例。</li>
</ol>
<p data-sourcepos="30:1-30:49">这个方法提供了一种灵活且类型安全的方式来批量注册服务,并允许您通过属性显式控制每个服务的生命周期。</p>
<p>  </p><br><br>
来源:https://www.cnblogs.com/wwwan/p/18868271
頁: [1]
查看完整版本: c# 批量注入示例代码