I have a use case where I want to register a service multiple times with different configs. The registration of this service is done in a builder extension method. Please check the below code for context.
SomeService
as a Singleton then it's not working because the ServiceCollection is not resolving the correct instance for me.NamedService
or KeyedService
but that option is not available here. Is there a way to effectively solve this problem?// a builder extension method
public static IServiceCollection AddSomeService(
this IServiceCollection services, string myConfig)
{
services.AddSingleton<TokenCredential>(fa =>
{
// a complex logic to register some singleton services which would be
// useful in below service registration
});
services.AddSingleton(fac => // Here I think, AddSingleton is not correct
{
ServiceCollection serviceCollection = new ServiceCollection();
// some complex logic using serviceCollection and myConfig goes here
ISomeService someService =
serviceCollection.BuildServiceProvider().GetSomeService();
return someService;
});
return services;
}
In Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddSomeService("dbConfig");
services.AddSingleton<DbRepo, IDbRepo>();
// I want to register SomeService again with different config and pass it
// to register CacheRepo
services.AddSomeService("cacheConfig");
services.AddSingleton<CacheRepo, ICacheRepo>();
}
public class DbRepo : IDbRepo
{
private readonly ISomeService someService;
public DbRepo (ISomeService someService)
{
this.someService = someService;
}
}
public class CacheRepo : ICacheRepo
{
private readonly ISomeService someService;
public CacheRepo (ISomeService someService)
{
this.someService = someService;
}
}
I would suggest using a factory class, e.g.:
public interface ISomeServiceFactory
{
ISomeService Create(string config);
}
public sealed class SomeServiceFactory : ISomeServiceFactory
{
private readonly IServiceProvider provider;
public SomeServiceFactory(IServiceProvider provider)
{
this.provider = provider;
}
public ISomeService Create(string config)
{
// do your processing here instead - you have access to the service provider
}
}
Then you can add that to the IServiceCollection
:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ISomeServiceFactory>(provider => new SomeServiceFactory(provider));
}
And inject that into your repos instead:
public class DbRepo : IDbRepo
{
private readonly ISomeService someService;
public DbRepo(ISomeServiceFactory factory)
{
this.someService = factory.Create("dbConfig");
}
}
public class CacheRepo : ICacheRepo
{
private readonly ISomeService someService;
public CacheRepo(ISomeServiceFactory factory)
{
this.someService = factory.Create("cacheConfig");
}
}