Search code examples
c#dependency-injectionservice.net-8.0ihostedservice

Add multiple singletons of the same service class to Dependency Injection in .NET 8


I need to add multiple instances of the same class to DI like this

program.cs

using PruebaWorkerService1;

var builder = Host.CreateApplicationBuilder(args);

builder.Services.AddHostedService<Worker>( x => new Worker("worker1"));
builder.Services.AddHostedService<Worker>(x => new Worker("worker2"));
builder.Services.AddHostedService<Worker>(x => new Worker("worker3"));

var host = builder.Build();
host.Run();

Worker.cs

namespace PruebaWorkerService1;

public class Worker : BackgroundService{

private readonly string _msg;

public Worker(string msg){

   this._msg = msg;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken){

   while (!stoppingToken. IsCancellationRequested){

      Console.WriteLine(("Worker running at: {time} {msg}", DateTimeOffset.Now, _msg));
      await Task.Delay(1000, stoppingToken);
   }
}

Result:

Result Only Worker1 was instanceated. I thought with diferent arguments (msg) it would create different instances. What do I need to do to create more than one instance of a service?


Solution

  • AddHostedService will add only the first service for type, the subsequent registrations will be ignored (internally it uses TryAddEnumerable). You have following options:

    1. Add a descendant type per the setting and register it, not Worker

    2. Use a hacky approach with manual registration via descriptor:

      builder.Services.Add(ServiceDescriptor.Singleton<IHostedService>(_ => new Worker("worker1")));
      builder.Services.Add(ServiceDescriptor.Singleton<IHostedService>(_ => new Worker("worker2")));
      builder.Services.Add(ServiceDescriptor.Singleton<IHostedService>(_ => new Worker("worker3")));
      
    3. Handle the settings in the worker, for example create a thread/task per the setting and run them in ExecuteAsync (for example check out this answer)