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

Time:03-18

Is it possible to add all IHostedService implemented classes in a loop without adding them individually in ASP.NET Core 6?

Let's say we have this two implementations:

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

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

The default way in Program.cs to add them is:

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

But, what about having a hundred implementations?

There has to be a better way to add (at runtime) the one hundred implementations in Program.cs without explicitly spelling out all their names!

CodePudding user response:

You can use an nuget package like this or you can create an extension method and get all references of services with reflection:

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));
   }
 }

and than call it at startup.cs

public void ConfigureServices(IServiceCollection services)
{
    // ....

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

But be careful , you are registering services in a collection. There is a long version of answer here. You should check.

CodePudding user response:

You can use scrutor which does assembly scanning (which it seems like what you want) https://andrewlock.net/using-scrutor-to-automatically-register-your-services-with-the-asp-net-core-di-container/

CodePudding user response:

The answer of @nzrytmn totally worked. Thank you very much!

I just made a few tweaks in RegisterAllTypes to fulfill my own requirements:

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));
}

Then in Program.cs:

builder.Services.RegisterAllTypes<IHostedService>();
  • Related