I have a factory method set up to return two different implementations of IDeployApplicationService
based on a string value.
I've tried a few permutations of .AddScoped()
or .AddTransient()
in Program.cs but not sure why this error keeps persisting.
My factory
public class DeployApplicationServiceFactory : IDeployApplicationServiceFactory
{
private readonly IServiceProvider serviceProvider;
public DeployApplicationServiceFactory(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
public IDeployApplicationService GetService(string environment)
{
if (environment.ToLower() == "prod")
{
// Error thrown in the line below.
// An exception of type 'System.InvalidOperationException' occurred
// in Microsoft.Extensions.DependencyInjection.Abstractions.dll
// but was not handled in user code: 'No service for type
// 'ProdDeployApplicationService' has been registered.'
return serviceProvider.GetRequiredService<ProdDeployApplicationService>();
}
else
{
return serviceProvider.GetRequiredService<NonProdDeployApplicationService>();
}
}
}
Program.cs (this is a worker)
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.ConfigureServices((hostContext, services) =>
{
//[...]
services.AddScoped<IDeployApplicationServiceFactory, DeployApplicationServiceFactory>();
services.AddScoped<IDeployApplicationService, ProdDeployApplicationService>();
services.AddScoped<IDeployApplicationService, NonProdDeployApplicationService>();
//[...]
}
CodePudding user response:
You've registered the service by its interface:
services.AddScoped<IDeployApplicationService, ProdDeployApplicationService>()
This means you can only resolve it by the interface serviceProvider.GetRequiredService<IDeployApplicationService>()
, and that would give you the last service registered by that interface, NonProdDeployApplicationService
.
Try registering it by itself (the implementation):
services.AddScoped<ProdDeployApplicationService>();
Now you can resolve the implementation directly:
serviceProvider.GetRequiredService<ProdDeployApplicationService>();
Keep in mind you can register a class multiple times: both by itself and by the interfaces/abstract classes it implements:
// this is ok
services.AddScoped<ProdDeployApplicationService>();
services.AddScoped<IDeployService, ProdDeployApplicationService>();
services.AddScoped<IDeployApplicationService, ProdDeployApplicationService>();
and resolve it using any key.