Home > Back-end >  How to register multiple implementations using factory pattern and Microsoft.Extensions.DependencyIn
How to register multiple implementations using factory pattern and Microsoft.Extensions.DependencyIn

Time:09-21

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.

  • Related