是否可以通过循环添加所有 IHostedService 类 (ASP.NET Core 6)?

Is it possible to add all IHostedService classes with a loop (ASP.NET Core 6)?

是否可以在循环中添加所有 IHostedService 实现的 类 而无需在 ASP.NET Core 6 中单独添加它们?

假设我们有这两个实现:

public class FirstImplementationOfHostedService : IHostedService 
{
    // ...
}

public class SecondImplementationOfHostedService : IHostedService 
{
    // ...
}

Program.cs 中的默认添加方式是:

builder.Services.AddHostedService<FirstImplementationOfHostedService>();
builder.Services.AddHostedService<SecondImplementationOfHostedService>();

但是,如果有一百个实现呢?

必须有更好的方法来添加(在运行时)Program.cs 中的一百个实现,而无需明确拼出它们的所有名称!

你可以使用 scrutor 进行程序集扫描(这似乎是你想要的)https://andrewlock.net/using-scrutor-to-automatically-register-your-services-with-the-asp-net-core-di-container/

您可以使用像 this 这样的 nuget 包,或者您可以创建一个扩展方法并通过反射获取所有服务引用:

public static class ServiceCollectionExtensions
{
   public static void RegisterAllTypes<T>(this IServiceCollection services, 
   Assembly[] assemblies,
    ServiceLifetime lifetime = ServiceLifetime.Transient)
   {
      var typesFromAssemblies = assemblies.SelectMany(a => 
       a.DefinedTypes.Where(x => x.GetInterfaces().Contains(typeof(T))));
      foreach (var type in typesFromAssemblies)
        services.Add(new ServiceDescriptor(typeof(T), type, lifetime));
   }
 }

然后在 startup.cs

调用它
public void ConfigureServices(IServiceCollection services)
{
    // ....

    services.RegisterAllTypes<IInvoicingService>(new[] { typeof(Startup).Assembly });
}

但请注意,您是在集合中注册服务。有一个长版本的答案 here。你应该检查一下。

@nzrytmn 的回答完全有效。非常感谢!

我刚刚在 RegisterAllTypes 中做了一些调整以满足我自己的要求:

public static void RegisterAllTypes<T>(this IServiceCollection services)
{
   var assemblies = new[] { Assembly.GetEntryAssembly() };

   var typesFromAssemblies = assemblies.SelectMany(a => a?.DefinedTypes.Where(x => x.GetInterfaces().Contains(typeof(T))));
   
   foreach (var type in typesFromAssemblies)
      services.Add(new ServiceDescriptor(typeof(T), type, ServiceLifetime.Singleton));
}

然后在 Program.cs:

builder.Services.RegisterAllTypes<IHostedService>();