[c#] How to register multiple implementations of the same interface in Asp.Net Core?

I have services that are derived from the same interface.

public interface IService { }
public class ServiceA : IService { }
public class ServiceB : IService { } 
public class ServiceC : IService { }

Typically, other IoC containers like Unity allow you to register concrete implementations by some Key that distinguishes them.

In ASP.NET Core, how do I register these services and resolve them at runtime based on some key?

I don't see any Add Service methods that take a key or name parameter, which would typically be used to distinguish the concrete implementation.

    public void ConfigureServices(IServiceCollection services)
    {            
         // How do I register services of the same interface?            
    }


    public MyController:Controller
    {
       public void DoSomething(string key)
       { 
          // How do I resolve the service by key?
       }
    }

Is the Factory pattern the only option here?

Update1
I have gone though the article here that shows how to use the factory pattern to get service instances when we have multiple concrete implementations. However, it is still not a complete solution. When I call the _serviceProvider.GetService() method, I cannot inject data into the constructor.

For example consider this:

public class ServiceA : IService
{
     private string _efConnectionString;
     ServiceA(string efconnectionString)
     {
       _efConnecttionString = efConnectionString;
     } 
}

public class ServiceB : IService
{    
   private string _mongoConnectionString;
   public ServiceB(string mongoConnectionString)
   {
      _mongoConnectionString = mongoConnectionString;
   }
}

public class ServiceC : IService
{    
    private string _someOtherConnectionString
    public ServiceC(string someOtherConnectionString)
    {
      _someOtherConnectionString = someOtherConnectionString;
    }
}

How can _serviceProvider.GetService() inject the appropriate connection string? In Unity, or any other IoC library, we can do that at type registration. I can use IOption, however, that will require me to inject all settings. I cannot inject a particular connection string into the service.

Also note that I am trying to avoid using other containers (including Unity) because then I have to register everything else (e.g., Controllers) with the new container as well.

Also, using the factory pattern to create service instances is against DIP, as it increases the number of dependencies a client has details here.

So, I think the default DI in ASP.NET Core is missing two things:

  1. The ability to register instances using a key
  2. The ability to inject static data into constructors during registration

This question is related to c# asp.net-core asp.net-core-mvc coreclr

The answer is


You're correct, the built in ASP.NET Core container does not have the concept of registering multiple services and then retrieving a specific one, as you suggest, a factory is the only real solution in that case.

Alternatively, you could switch to a third party container like Unity or StructureMap that does provide the solution you need (documented here: https://docs.asp.net/en/latest/fundamentals/dependency-injection.html?#replacing-the-default-services-container).


Another option is to use the extension method GetServices from Microsoft.Extensions.DependencyInjection.

Register your services as:

services.AddSingleton<IService, ServiceA>();
services.AddSingleton<IService, ServiceB>();
services.AddSingleton<IService, ServiceC>();

Then resolve with a little of Linq:

var services = serviceProvider.GetServices<IService>();
var serviceB = services.First(o => o.GetType() == typeof(ServiceB));

or

var serviceZ = services.First(o => o.Name.Equals("Z"));

(assuming that IService has a string property called "Name")

Make sure to have using Microsoft.Extensions.DependencyInjection;

Update

AspNet 2.1 source: GetServices


I have run into the same problem and I worked with a simple extension to allow Named services. You can find it here:

It allows you to add as many (named) services as you want like this:

 var serviceCollection = new ServiceCollection();
 serviceCollection.Add(typeof(IMyService), typeof(MyServiceA), "A", ServiceLifetime.Transient);
 serviceCollection.Add(typeof(IMyService), typeof(MyServiceB), "B", ServiceLifetime.Transient);

 var serviceProvider = serviceCollection.BuildServiceProvider();

 var myServiceA = serviceProvider.GetService<IMyService>("A");
 var myServiceB = serviceProvider.GetService<IMyService>("B");

The library also allows you to easy implement a "factory pattern" like this:

    [Test]
    public void FactoryPatternTest()
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection.Add(typeof(IMyService), typeof(MyServiceA), MyEnum.A.GetName(), ServiceLifetime.Transient);
        serviceCollection.Add(typeof(IMyService), typeof(MyServiceB), MyEnum.B.GetName(), ServiceLifetime.Transient);

        serviceCollection.AddTransient<IMyServiceFactoryPatternResolver, MyServiceFactoryPatternResolver>();

        var serviceProvider = serviceCollection.BuildServiceProvider();

        var factoryPatternResolver = serviceProvider.GetService<IMyServiceFactoryPatternResolver>();

        var myServiceA = factoryPatternResolver.Resolve(MyEnum.A);
        Assert.NotNull(myServiceA);
        Assert.IsInstanceOf<MyServiceA>(myServiceA);

        var myServiceB = factoryPatternResolver.Resolve(MyEnum.B);
        Assert.NotNull(myServiceB);
        Assert.IsInstanceOf<MyServiceB>(myServiceB);
    }

    public interface IMyServiceFactoryPatternResolver : IFactoryPatternResolver<IMyService, MyEnum>
    {
    }

    public class MyServiceFactoryPatternResolver : FactoryPatternResolver<IMyService, MyEnum>, IMyServiceFactoryPatternResolver
    {
        public MyServiceFactoryPatternResolver(IServiceProvider serviceProvider)
        : base(serviceProvider)
        {
        }
    }

    public enum MyEnum
    {
        A = 1,
        B = 2
    }

Hope it helps


A factory approach is certainly viable. Another approach is to use inheritance to create individual interfaces that inherit from IService, implement the inherited interfaces in your IService implementations, and register the inherited interfaces rather than the base. Whether adding an inheritance hierarchy or factories is the "right" pattern all depends on who you speak to. I often have to use this pattern when dealing with multiple database providers in the same application that uses a generic, such as IRepository<T>, as the foundation for data access.

Example interfaces and implementations:

public interface IService 
{
}

public interface IServiceA: IService
{}

public interface IServiceB: IService
{}

public IServiceC: IService
{}

public class ServiceA: IServiceA 
{}

public class ServiceB: IServiceB
{}

public class ServiceC: IServiceC
{}

Container:

container.Register<IServiceA, ServiceA>();
container.Register<IServiceB, ServiceB>();
container.Register<IServiceC, ServiceC>();

After reading the answers here and articles elsewhere I was able to get it working without strings. When you have multiple implementations of the same interface the DI will add these to a collection, so it's then possible to retrieve the version you want from the collection using typeof.

// In Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped(IService, ServiceA);
    services.AddScoped(IService, ServiceB);
    services.AddScoped(IService, ServiceC);
}

// Any class that uses the service(s)
public class Consumer
{
    private readonly IEnumerable<IService> _myServices;

    public Consumer(IEnumerable<IService> myServices)
    {
        _myServices = myServices;
    }

    public UseServiceA()
    {
        var serviceA = _myServices.FirstOrDefault(t => t.GetType() == typeof(ServiceA));
        serviceA.DoTheThing();
    }

    public UseServiceB()
    {
        var serviceB = _myServices.FirstOrDefault(t => t.GetType() == typeof(ServiceB));
        serviceB.DoTheThing();
    }

    public UseServiceC()
    {
        var serviceC = _myServices.FirstOrDefault(t => t.GetType() == typeof(ServiceC));
        serviceC.DoTheThing();
    }
}

since my post above, I have moved to a Generic Factory Class

Usage

 services.AddFactory<IProcessor, string>()
         .Add<ProcessorA>("A")
         .Add<ProcessorB>("B");

 public MyClass(IFactory<IProcessor, string> processorFactory)
 {
       var x = "A"; //some runtime variable to select which object to create
       var processor = processorFactory.Create(x);
 }

Implementation

public class FactoryBuilder<I, P> where I : class
{
    private readonly IServiceCollection _services;
    private readonly FactoryTypes<I, P> _factoryTypes;
    public FactoryBuilder(IServiceCollection services)
    {
        _services = services;
        _factoryTypes = new FactoryTypes<I, P>();
    }
    public FactoryBuilder<I, P> Add<T>(P p)
        where T : class, I
    {
        _factoryTypes.ServiceList.Add(p, typeof(T));

        _services.AddSingleton(_factoryTypes);
        _services.AddTransient<T>();
        return this;
    }
}
public class FactoryTypes<I, P> where I : class
{
    public Dictionary<P, Type> ServiceList { get; set; } = new Dictionary<P, Type>();
}

public interface IFactory<I, P>
{
    I Create(P p);
}

public class Factory<I, P> : IFactory<I, P> where I : class
{
    private readonly IServiceProvider _serviceProvider;
    private readonly FactoryTypes<I, P> _factoryTypes;
    public Factory(IServiceProvider serviceProvider, FactoryTypes<I, P> factoryTypes)
    {
        _serviceProvider = serviceProvider;
        _factoryTypes = factoryTypes;
    }

    public I Create(P p)
    {
        return (I)_serviceProvider.GetService(_factoryTypes.ServiceList[p]);
    }
}

Extension

namespace Microsoft.Extensions.DependencyInjection
{
    public static class DependencyExtensions
    {
        public static FactoryBuilder<I, P> AddFactory<I, P>(this IServiceCollection services)
            where I : class
        {
            services.AddTransient<IFactory<I, P>, Factory<I, P>>();
            return new FactoryBuilder<I, P>(services);
        }
    }
}

I've faced the same issue and want to share how I solved it and why.

As you mentioned there are two problems. The first:

In Asp.Net Core how do I register these services and resolve it at runtime based on some key?

So what options do we have? Folks suggest two:

  • Use a custom factory (like _myFactory.GetServiceByKey(key))

  • Use another DI engine (like _unityContainer.Resolve<IService>(key))

Is the Factory pattern the only option here?

In fact both options are factories because each IoC Container is also a factory (highly configurable and complicated though). And it seems to me that other options are also variations of the Factory pattern.

So what option is better then? Here I agree with @Sock who suggested using custom factory, and that is why.

First, I always try to avoid adding new dependencies when they are not really needed. So I agree with you in this point. Moreover, using two DI frameworks is worse than creating custom factory abstraction. In the second case you have to add new package dependency (like Unity) but depending on a new factory interface is less evil here. The main idea of ASP.NET Core DI, I believe, is simplicity. It maintains a minimal set of features following KISS principle. If you need some extra feature then DIY or use a corresponding Plungin that implements desired feature (Open Closed Principle).

Secondly, often we need to inject many named dependencies for single service. In case of Unity you may have to specify names for constructor parameters (using InjectionConstructor). This registration uses reflection and some smart logic to guess arguments for the constructor. This also may lead to runtime errors if registration does not match the constructor arguments. From the other hand, when using your own factory you have full control of how to provide the constructor parameters. It's more readable and it's resolved at compile-time. KISS principle again.

The second problem:

How can _serviceProvider.GetService() inject appropriate connection string?

First, I agree with you that depending on new things like IOptions (and therefore on package Microsoft.Extensions.Options.ConfigurationExtensions) is not a good idea. I've seen some discussing about IOptions where there were different opinions about its benifit. Again, I try to avoid adding new dependencies when they are not really needed. Is it really needed? I think no. Otherwise each implementation would have to depend on it without any clear need coming from that implementation (for me it looks like violation of ISP, where I agree with you too). This is also true about depending on the factory but in this case it can be avoided.

The ASP.NET Core DI provides a very nice overload for that purpose:

var mongoConnection = //...
var efConnection = //...
var otherConnection = //...
services.AddTransient<IMyFactory>(
             s => new MyFactoryImpl(
                 mongoConnection, efConnection, otherConnection, 
                 s.GetService<ISomeDependency1>(), s.GetService<ISomeDependency2>())));

I just simply inject an IEnumerable

ConfigureServices in Startup.cs

Assembly.GetEntryAssembly().GetTypesAssignableFrom<IService>().ForEach((t)=>
                {
                    services.AddScoped(typeof(IService), t);
                });

Services Folder

public interface IService
{
    string Name { get; set; }
}

public class ServiceA : IService
{
    public string Name { get { return "A"; } }
}

public class ServiceB : IService
{    
    public string Name { get { return "B"; } }
}

public class ServiceC : IService
{    
    public string Name { get { return "C"; } }
}

MyController.cs

public class MyController
{
    private readonly IEnumerable<IService> _services;
    public MyController(IEnumerable<IService> services)
    {
        _services = services;
    }
    public void DoSomething()
    {
        var service = _services.Where(s => s.Name == "A").Single();
    }
...
}

Extensions.cs

    public static List<Type> GetTypesAssignableFrom<T>(this Assembly assembly)
    {
        return assembly.GetTypesAssignableFrom(typeof(T));
    }
    public static List<Type> GetTypesAssignableFrom(this Assembly assembly, Type compareType)
    {
        List<Type> ret = new List<Type>();
        foreach (var type in assembly.DefinedTypes)
        {
            if (compareType.IsAssignableFrom(type) && compareType != type)
            {
                ret.Add(type);
            }
        }
        return ret;
    }

I think the solution described in the following article "Resolución dinámica de tipos en tiempo de ejecución en el contenedor de IoC de .NET Core" is simpler and does not require factories.

You could use a generic interface

public interface IService<T> where T : class {}

then register the desired types on the IoC container:

services.AddTransient<IService<ServiceA>, ServiceA>();
services.AddTransient<IService<ServiceB>, ServiceB>();

After that you must declare the dependencies as follow:

private readonly IService<ServiceA> _serviceA;
private readonly IService<ServiceB> _serviceB;

public WindowManager(IService<ServiceA> serviceA, IService<ServiceB> serviceB)
{
    this._serviceA = serviceA ?? throw new ArgumentNullException(nameof(serviceA));
    this._serviceB = serviceB ?? throw new ArgumentNullException(nameof(ServiceB));
}

I didn't have time to read through them all but it seemed everyone was providing solutions to problems that shouldn't exist in the first place.

If you need all of the registered IService implementations then you need them all. But DO NOT inject them all with IEnumerable and then use logic to select one based on some type of key. Problem with doing that is you need a key and the logic should not need to change if the key changes ie; different implementation of IService so typeof doesn't work any more.

The Real Problem

There is business logic here that should be in an engine service. Something like IServiceDecisionEngine is needed. The implementation of the IServiceDecisionEngine gets ONLY the needed IService implementations from DI. Like

public class ServiceDecisionEngine<SomeData>: IServiceDecisionEngine<T> 
{
    public ServiceDecisionEngine(IService serviceA, IService serviceB) { }

    public IService ResolveService(SomeData dataNeededForLogic)
    {
        if (dataNeededForLogic.someValue == true) 
        { 
            return serviceA;
        } 
        return serviceB;
    }
}

Now in your DI, you can do .AddScoped<IServiceDecisionEngine<SomeData>, new ServiceDecisionEngine(new ServiceA(), new ServiceB()) and the managerService that needs an IService will get it by injecting and using IServiceDecisionEngine.


Why not use inheritance? This way we can have as many copies of the interface as we want and we can pick suitable names for each of them . And we have a benefit of type safety

public interface IReportGenerator
public interface IExcelReportGenerator : IReportGenerator
public interface IPdfReportGenerator : IReportGenerator

Concrete classes:

public class ExcelReportGenerator : IExcelReportGenerator
public class PdfReportGenerator : IPdfReportGenerator

Register:

instead of

services.AddScoped<IReportGenerator, PdfReportGenerator>();
services.AddScoped<IReportGenerator, ExcelReportGenerator>();

we have :

services.AddScoped<IPdfReportGenerator, PdfReportGenerator>();
services.AddScoped<IExcelReportGenerator, ExcelReportGenerator>();

Client:

public class ReportManager : IReportManager
{
    private readonly IExcelReportGenerator excelReportGenerator;
    private readonly IPdfReportGenerator pdfReportGenerator;

    public ReportManager(IExcelReportGenerator excelReportGenerator, 
                         IPdfReportGenerator pdfReportGenerator)
    {
        this.excelReportGenerator = excelReportGenerator;
        this.pdfReportGenerator = pdfReportGenerator;
    }

this approach also allows for louse coupled code, because we can move IReportGenerator to the core of the application and have child interfaces that will be declared at higher levels.


While the out of the box implementation doesn't offer it, here's a sample project that allows you to register named instances, and then inject INamedServiceFactory into your code and pull out instances by name. Unlike other facory solutions here, it will allow you to register multiple instances of same implementation but configured differently

https://github.com/macsux/DotNetDINamedInstances


How about this? You can probably take it a step further and use route instead of enum to resolve service type.

Interface which is typed to a Parent Class where BalanceSheetReportDto : ReportDto

public interface IReportService<T> where T : ReportDto
{
    Task<byte[]> GetFileStream(T reportDto);
}

An abstract class that implements it.

public abstract class ReportService : IReportService<ReportDto>
    {
        public abstract Task<byte[]> GetFileStream(ReportDto reportDto);

    }

This abstract class is what we need to resolve concrete types as you will not be able to specify resolver type as IReportService<ReportDto> and return implementation BalaceSheetReportService. Look at next code block.

Service Resolver for DI.

public delegate ReportService ServiceResolver(ReportType key);
    public static IServiceCollection AddReportServices(this IServiceCollection services)
    {
        services.AddScoped<BalanceSheetReportService>();
        
        services.AddScoped<ServiceResolver>(serviceProvider => key =>  
        {  
            switch (key)  
            {  
                case ReportType.BalanceSheet:  
                    return serviceProvider.GetService<BalanceSheetReportService>();
                default:
                    throw new KeyNotFoundException();  
            }  
        });  

And in controller add resolver but not need to cast to specific type.

public class FinancialReportsController : BaseController
    {
        private ServiceCollectionExtension.ServiceResolver _resolver;
    ...
    [HttpPost("balance-sheet")]              
        public async Task<byte[]> GetBalanceSheetReport([FromBody] BalanceSheetReportDto request)
        {
            try
            {
                var reportService =  _resolver(ReportType.BalanceSheet); //magic
                var data = await reportService.GetFileStream(request);

Concrete implementation.

public class BalanceSheetReportService: ReportService 
    {
    ...
    public override async Task<byte[]> GetFileStream(ReportDto reportDto)
        {
            return await GetFileStream((BalanceSheetReportDto) reportDto);
        }

        private  async Task<byte[]> GetFileStream(BalanceSheetReportDto reportDto)
        {

Unrelated but you could inject other services (data classes for example) to abstract class.

private MongoDbContext _context;
 public ReportService(MongoDbContext context) {
 _context = context;
}

And then in your subclasses call this constructor and be done with it.

public BalanceSheetReportService(MongoDbContext context) : base(context) {}

I know this post is a couple years old, but I keep running into this and I'm not happy with the service locator pattern.

Also, I know the OP is looking for an implementation which allows you to choose a concrete implementation based on a string. I also realize that the OP is specifically asking for an implementation of an identical interface. The solution I'm about to describe relies on adding a generic type parameter to your interface. The problem is that you don't have any real use for the type parameter other than service collection binding. I'll try to describe a situation which might require something like this.

Imagine configuration for such a scenario in appsettings.json which might look something like this (this is just for demonstration, your configuration can come from wherever you want as long as you have the correction configuration provider):

{
  "sqlDataSource": {
    "connectionString": "Data Source=localhost; Initial catalog=Foo; Connection Timeout=5; Encrypt=True;",
    "username": "foo",
    "password": "this normally comes from a secure source, but putting here for demonstration purposes"
  },
  "mongoDataSource": {
    "hostName": "uw1-mngo01-cl08.company.net",
    "port": 27026,
    "collection": "foo"
  }
}

You really need a type that represents each of your configuration options:

public class SqlDataSource
{
  public string ConnectionString { get;set; }
  public string Username { get;set; }
  public string Password { get;set; }
}

public class MongoDataSource
{
  public string HostName { get;set; }
  public string Port { get;set; }
  public string Collection { get;set; }
}

Now, I know that it might seem a little contrived to have two implementations of the same interface, but it I've definitely seen it in more than one case. The ones I usually come across are:

  1. When migrating from one data store to another, it's useful to be able to implement the same logical operations using the same interfaces so that you don't need to change the calling code. This also allows you to add configuration which swaps between different implementations at runtime (which can be useful for rollback).
  2. When using the decorator pattern. The reason you might use that pattern is that you want to add functionality without changing the interface and fall back to the existing functionality in certain cases (I've used it when adding caching to repository classes because I want circuit breaker-like logic around connections to the cache that fall back to the base repository -- this gives me optimal behavior when the cache is available, but behavior that still functions when it's not).

Anyway, you can reference them by adding a type parameter to your service interface so that you can implement the different implementations:

public interface IService<T> {
  void DoServiceOperation();
}

public class MongoService : IService<MongoDataSource> {
  private readonly MongoDataSource _options;

  public FooService(IOptionsMonitor<MongoDataSource> serviceOptions){
    _options = serviceOptions.CurrentValue
  }

  void DoServiceOperation(){
    //do something with your mongo data source options (connect to database)
    throw new NotImplementedException();
  }
}

public class SqlService : IService<SqlDataSource> {
  private readonly SqlDataSource_options;

  public SqlService (IOptionsMonitor<SqlDataSource> serviceOptions){
    _options = serviceOptions.CurrentValue
  }

  void DoServiceOperation(){
    //do something with your sql data source options (connect to database)
    throw new NotImplementedException();
  }
}

In startup, you'd register these with the following code:

services.Configure<SqlDataSource>(configurationSection.GetSection("sqlDataSource"));
services.Configure<MongoDataSource>(configurationSection.GetSection("mongoDataSource"));

services.AddTransient<IService<SqlDataSource>, SqlService>();
services.AddTransient<IService<MongoDataSource>, MongoService>();

Finally in the class which relies on the Service with a different connection, you just take a dependency on the service you need and the DI framework will take care of the rest:

[Route("api/v1)]
[ApiController]
public class ControllerWhichNeedsMongoService {  
  private readonly IService<MongoDataSource> _mongoService;
  private readonly IService<SqlDataSource> _sqlService ;

  public class ControllerWhichNeedsMongoService(
    IService<MongoDataSource> mongoService, 
    IService<SqlDataSource> sqlService
  )
  {
    _mongoService = mongoService;
    _sqlService = sqlService;
  }

  [HttpGet]
  [Route("demo")]
  public async Task GetStuff()
  {
    if(useMongo)
    {
       await _mongoService.DoServiceOperation();
    }
    await _sqlService.DoServiceOperation();
  }
}

These implementations can even take a dependency on each other. The other big benefit is that you get compile-time binding so any refactoring tools will work correctly.

Hope this helps someone in the future.


I created my own extension over IServiceCollection used WithName extension:

public static IServiceCollection AddScopedWithName<TService, TImplementation>(this IServiceCollection services, string serviceName)
        where TService : class
        where TImplementation : class, TService
    {
        Type serviceType = typeof(TService);
        Type implementationServiceType = typeof(TImplementation);
        ServiceCollectionTypeMapper.Instance.AddDefinition(serviceType.Name, serviceName, implementationServiceType.AssemblyQualifiedName);
        services.AddScoped<TImplementation>();
        return services;
    }

ServiceCollectionTypeMapper is a singleton instance that maps IService > NameOfService > Implementation where an interface could have many implementations with different names, this allows to register types than we can resolve when wee need and is a different approach than resolve multiple services to select what we want.

 /// <summary>
/// Allows to set the service register mapping.
/// </summary>
public class ServiceCollectionTypeMapper
{
    private ServiceCollectionTypeMapper()
    {
        this.ServiceRegister = new Dictionary<string, Dictionary<string, string>>();
    }

    /// <summary>
    /// Gets the instance of mapper.
    /// </summary>
    public static ServiceCollectionTypeMapper Instance { get; } = new ServiceCollectionTypeMapper();

    private Dictionary<string, Dictionary<string, string>> ServiceRegister { get; set; }

    /// <summary>
    /// Adds new service definition.
    /// </summary>
    /// <param name="typeName">The name of the TService.</param>
    /// <param name="serviceName">The TImplementation name.</param>
    /// <param name="namespaceFullName">The TImplementation AssemblyQualifiedName.</param>
    public void AddDefinition(string typeName, string serviceName, string namespaceFullName)
    {
        if (this.ServiceRegister.TryGetValue(typeName, out Dictionary<string, string> services))
        {
            if (services.TryGetValue(serviceName, out _))
            {
                throw new InvalidOperationException($"Exists an implementation with the same name [{serviceName}] to the type [{typeName}].");
            }
            else
            {
                services.Add(serviceName, namespaceFullName);
            }
        }
        else
        {
            Dictionary<string, string> serviceCollection = new Dictionary<string, string>
            {
                { serviceName, namespaceFullName },
            };
            this.ServiceRegister.Add(typeName, serviceCollection);
        }
    }

    /// <summary>
    /// Get AssemblyQualifiedName of implementation.
    /// </summary>
    /// <typeparam name="TService">The type of the service implementation.</typeparam>
    /// <param name="serviceName">The name of the service.</param>
    /// <returns>The AssemblyQualifiedName of the inplementation service.</returns>
    public string GetService<TService>(string serviceName)
    {
        Type serviceType = typeof(TService);

        if (this.ServiceRegister.TryGetValue(serviceType.Name, out Dictionary<string, string> services))
        {
            if (services.TryGetValue(serviceName, out string serviceImplementation))
            {
                return serviceImplementation;
            }
            else
            {
                return null;
            }
        }
        else
        {
            return null;
        }
    }

To register a new service:

services.AddScopedWithName<IService, MyService>("Name");

To resolve service we need an extension over IServiceProvider like this.

/// <summary>
    /// Gets the implementation of service by name.
    /// </summary>
    /// <typeparam name="T">The type of service.</typeparam>
    /// <param name="serviceProvider">The service provider.</param>
    /// <param name="serviceName">The service name.</param>
    /// <returns>The implementation of service.</returns>
    public static T GetService<T>(this IServiceProvider serviceProvider, string serviceName)
    {
        string fullnameImplementation = ServiceCollectionTypeMapper.Instance.GetService<T>(serviceName);
        if (fullnameImplementation == null)
        {
            throw new InvalidOperationException($"Unable to resolve service of type [{typeof(T)}] with name [{serviceName}]");
        }
        else
        {
            return (T)serviceProvider.GetService(Type.GetType(fullnameImplementation));
        }
    }

When resolve:

serviceProvider.GetService<IWithdrawalHandler>(serviceName);

Remember that serviceProvider can be injected within a constructor in our application as IServiceProvider.

I hope this helps.


Bit late to this party, but here is my solution:...

Startup.cs or Program.cs if Generic Handler...

services.AddTransient<IMyInterface<CustomerSavedConsumer>, CustomerSavedConsumer>();
services.AddTransient<IMyInterface<ManagerSavedConsumer>, ManagerSavedConsumer>();

IMyInterface of T Interface Setup

public interface IMyInterface<T> where T : class, IMyInterface<T>
{
    Task Consume();
}

Concrete implementations of IMyInterface of T

public class CustomerSavedConsumer: IMyInterface<CustomerSavedConsumer>
{
    public async Task Consume();
}

public class ManagerSavedConsumer: IMyInterface<ManagerSavedConsumer>
{
    public async Task Consume();
}

Hopefully if there is any issue with doing it this way, someone will kindly point out why this is the wrong way to do this.


FooA, FooB and FooC implements IFoo

Services Provider:

services.AddTransient<FooA>(); // Note that there is no interface
services.AddTransient<FooB>();
services.AddTransient<FooC>();

services.AddSingleton<Func<Type, IFoo>>(x => type =>
{
    return (IFoo)x.GetService(type);
});

Destination:

public class Test
{
    private readonly IFoo foo;

    public Test(Func<Type, IFoo> fooFactory)
    {
        foo = fooFactory(typeof(FooA));
    }

    ....

}

If you want to change the FooA to FooAMock for test purposes:

services.AddTransient<FooAMock>();

services.AddSingleton<Func<Type, IFoo>>(x => type =>
{
    if(type.Equals(typeof(FooA))
        return (IFoo)x.GetService(typeof(FooAMock));
    return null;
});

Extending the solution of @rnrneverdies. Instead of ToString(), following options can also be used- 1) With common property implementation, 2) A service of services suggested by @Craig Brunetti.

public interface IService { }
public class ServiceA : IService
{
    public override string ToString()
    {
        return "A";
    }
}

public class ServiceB : IService
{
    public override string ToString()
    {
        return "B";
    }

}

/// <summary>
/// extension method that compares with ToString value of an object and returns an object if found
/// </summary>
public static class ServiceProviderServiceExtensions
{
    public static T GetService<T>(this IServiceProvider provider, string identifier)
    {
        var services = provider.GetServices<T>();
        var service = services.FirstOrDefault(o => o.ToString() == identifier);
        return service;
    }
}

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

    services.AddSingleton<IService, ServiceA>();
    services.AddSingleton<IService, ServiceB>();
    services.AddSingleton<IService, ServiceC>();

    var sp = services.BuildServiceProvider();
    var a = sp.GetService<IService>("A"); //returns instance of ServiceA
    var b = sp.GetService<IService>("B"); //returns instance of ServiceB

    //Remaining configurations....
}

I have created a library for this that implements some nice features. Code can be found on GitHub: https://github.com/dazinator/Dazinator.Extensions.DependencyInjection NuGet: https://www.nuget.org/packages/Dazinator.Extensions.DependencyInjection/

Usage is straightforward:

  1. Add the Dazinator.Extensions.DependencyInjection nuget package to your project.
  2. Add your Named Service registrations.
    var services = new ServiceCollection();
    services.AddNamed<AnimalService>(names =>
    {
        names.AddSingleton("A"); // will resolve to a singleton instance of AnimalService
        names.AddSingleton<BearService>("B"); // will resolve to a singleton instance of BearService (which derives from AnimalService)
        names.AddSingleton("C", new BearService()); will resolve to singleton instance provided yourself.
        names.AddSingleton("D", new DisposableTigerService(), registrationOwnsInstance = true); // will resolve to singleton instance provided yourself, but will be disposed for you (if it implements IDisposable) when this registry is disposed (also a singleton).

        names.AddTransient("E"); // new AnimalService() every time..
        names.AddTransient<LionService>("F"); // new LionService() every time..

        names.AddScoped("G");  // scoped AnimalService
        names.AddScoped<DisposableTigerService>("H");  scoped DisposableTigerService and as it implements IDisposable, will be disposed of when scope is disposed of.

    });


In the example above, notice that for each named registration, you are also specifying the lifetime or Singleton, Scoped, or Transient.

You can resolve services in one of two ways, depending on if you are comfortable with having your services take a dependency on this package of not:

public MyController(Func<string, AnimalService> namedServices)
{
   AnimalService serviceA = namedServices("A");
   AnimalService serviceB = namedServices("B"); // BearService derives from AnimalService
}

or

public MyController(NamedServiceResolver<AnimalService> namedServices)
{
   AnimalService serviceA = namedServices["A"];
   AnimalService serviceB = namedServices["B"]; // instance of BearService returned derives from AnimalService
}

I have specifically designed this library to work well with Microsoft.Extensions.DependencyInjection - for example:

  1. When you register named services, any types that you register can have constructors with parameters - they will be satisfied via DI, in the same way that AddTransient<>, AddScoped<> and AddSingleton<> methods work ordinarily.

  2. For transient and scoped named services, the registry builds an ObjectFactory so that it can activate new instances of the type very quickly when needed. This is much faster than other approaches and is in line with how Microsoft.Extensions.DependencyInjection does things.


While it seems @Miguel A. Arilla has pointed it out clearly and I voted up for him, I created on top of his useful solution another solution which looks neat but requires a lot more work.

It definitely depends on the above solution. So basically I created something similar to Func<string, IService>> and I called it IServiceAccessor as an interface and then I had to add a some more extensions to the IServiceCollection as such:

public static IServiceCollection AddSingleton<TService, TImplementation, TServiceAccessor>(
            this IServiceCollection services,
            string instanceName
        )
            where TService : class
            where TImplementation : class, TService
            where TServiceAccessor : class, IServiceAccessor<TService>
        {
            services.AddSingleton<TService, TImplementation>();
            services.AddSingleton<TServiceAccessor>();
            var provider = services.BuildServiceProvider();
            var implementationInstance = provider.GetServices<TService>().Last();
            var accessor = provider.GetServices<TServiceAccessor>().First();

            var serviceDescriptors = services.Where(d => d.ServiceType == typeof(TServiceAccessor));
            while (serviceDescriptors.Any())
            {
                services.Remove(serviceDescriptors.First());
            }

            accessor.SetService(implementationInstance, instanceName);
            services.AddSingleton<TServiceAccessor>(prvd => accessor);
            return services;
        }

The service Accessor looks like:

 public interface IServiceAccessor<TService>
    {
         void Register(TService service,string name);
         TService Resolve(string name);

    }

The end result,you will be able to register services with names or named instances like we used to do with other containers..for instance:

    services.AddSingleton<IEncryptionService, SymmetricEncryptionService, EncyptionServiceAccessor>("Symmetric");
    services.AddSingleton<IEncryptionService, AsymmetricEncryptionService, EncyptionServiceAccessor>("Asymmetric");

That is enough for now, but to make your work complete, it is better to add more extension methods as you can to cover all types of registrations following the same approach.

There was another post on stackoverflow, but I can not find it, where the poster has explained in details why this feature is not supported and how to work around it, basically similar to what @Miguel stated. It was nice post even though I do not agree with each point because I think there are situation where you really need named instances. I will post that link here once I find it again.

As a matter of fact, you do not need to pass that Selector or Accessor:

I am using the following code in my project and it worked well so far.

 /// <summary>
    /// Adds the singleton.
    /// </summary>
    /// <typeparam name="TService">The type of the t service.</typeparam>
    /// <typeparam name="TImplementation">The type of the t implementation.</typeparam>
    /// <param name="services">The services.</param>
    /// <param name="instanceName">Name of the instance.</param>
    /// <returns>IServiceCollection.</returns>
    public static IServiceCollection AddSingleton<TService, TImplementation>(
        this IServiceCollection services,
        string instanceName
    )
        where TService : class
        where TImplementation : class, TService
    {
        var provider = services.BuildServiceProvider();
        var implementationInstance = provider.GetServices<TService>().LastOrDefault();
        if (implementationInstance.IsNull())
        {
            services.AddSingleton<TService, TImplementation>();
            provider = services.BuildServiceProvider();
            implementationInstance = provider.GetServices<TService>().Single();
        }
        return services.RegisterInternal(instanceName, provider, implementationInstance);
    }

    private static IServiceCollection RegisterInternal<TService>(this IServiceCollection services,
        string instanceName, ServiceProvider provider, TService implementationInstance)
        where TService : class
    {
        var accessor = provider.GetServices<IServiceAccessor<TService>>().LastOrDefault();
        if (accessor.IsNull())
        {
            services.AddSingleton<ServiceAccessor<TService>>();
            provider = services.BuildServiceProvider();
            accessor = provider.GetServices<ServiceAccessor<TService>>().Single();
        }
        else
        {
            var serviceDescriptors = services.Where(d => d.ServiceType == typeof(IServiceAccessor<TService>));
            while (serviceDescriptors.Any())
            {
                services.Remove(serviceDescriptors.First());
            }
        }
        accessor.Register(implementationInstance, instanceName);
        services.AddSingleton<TService>(prvd => implementationInstance);
        services.AddSingleton<IServiceAccessor<TService>>(prvd => accessor);
        return services;
    }

    //
    // Summary:
    //     Adds a singleton service of the type specified in TService with an instance specified
    //     in implementationInstance to the specified Microsoft.Extensions.DependencyInjection.IServiceCollection.
    //
    // Parameters:
    //   services:
    //     The Microsoft.Extensions.DependencyInjection.IServiceCollection to add the service
    //     to.
    //   implementationInstance:
    //     The instance of the service.
    //   instanceName:
    //     The name of the instance.
    //
    // Returns:
    //     A reference to this instance after the operation has completed.
    public static IServiceCollection AddSingleton<TService>(
        this IServiceCollection services,
        TService implementationInstance,
        string instanceName) where TService : class
    {
        var provider = services.BuildServiceProvider();
        return RegisterInternal(services, instanceName, provider, implementationInstance);
    }

    /// <summary>
    /// Registers an interface for a class
    /// </summary>
    /// <typeparam name="TInterface">The type of the t interface.</typeparam>
    /// <param name="services">The services.</param>
    /// <returns>IServiceCollection.</returns>
    public static IServiceCollection As<TInterface>(this IServiceCollection services)
         where TInterface : class
    {
        var descriptor = services.Where(d => d.ServiceType.GetInterface(typeof(TInterface).Name) != null).FirstOrDefault();
        if (descriptor.IsNotNull())
        {
            var provider = services.BuildServiceProvider();
            var implementationInstance = (TInterface)provider?.GetServices(descriptor?.ServiceType)?.Last();
            services?.AddSingleton(implementationInstance);
        }
        return services;
    }

It is not supported by Microsoft.Extensions.DependencyInjection.

But you can plug-in another dependency injection mechanism, like StructureMap See it's Home page and it's GitHub Project.

It's not hard at all:

  1. Add a dependency to StructureMap in your project.json:

    "Structuremap.Microsoft.DependencyInjection" : "1.0.1",
    
  2. Inject it into the ASP.NET pipeline inside ConfigureServices and register your classes (see docs)

    public IServiceProvider ConfigureServices(IServiceCollection services) // returns IServiceProvider !
    {
        // Add framework services.
        services.AddMvc();
        services.AddWhatever();
    
        //using StructureMap;
        var container = new Container();
        container.Configure(config =>
        {
            // Register stuff in container, using the StructureMap APIs...
            config.For<IPet>().Add(new Cat("CatA")).Named("A");
            config.For<IPet>().Add(new Cat("CatB")).Named("B");
            config.For<IPet>().Use("A"); // Optionally set a default
            config.Populate(services);
        });
    
        return container.GetInstance<IServiceProvider>();
    }
    
  3. Then, to get a named instance, you will need to request the IContainer

    public class HomeController : Controller
    {
        public HomeController(IContainer injectedContainer)
        {
            var myPet = injectedContainer.GetInstance<IPet>("B");
            string name = myPet.Name; // Returns "CatB"
    

That's it.

For the example to build, you need

    public interface IPet
    {
        string Name { get; set; }
    }

    public class Cat : IPet
    {
        public Cat(string name)
        {
            Name = name;
        }

        public string Name {get; set; }
    }

How about a service for services?

If we had an INamedService interface (with .Name property), we could write an IServiceCollection extension for .GetService(string name), where the extension would take that string parameter, and do a .GetServices() on itself, and in each returned instance, find the instance whose INamedService.Name matches the given name.

Like this:

public interface INamedService
{
    string Name { get; }
}

public static T GetService<T>(this IServiceProvider provider, string serviceName)
    where T : INamedService
{
    var candidates = provider.GetServices<T>();
    return candidates.FirstOrDefault(s => s.Name == serviceName);
}

Therefore, your IMyService must implement INamedService, but you'll get the key-based resolution you want, right?

To be fair, having to even have this INamedService interface seems ugly, but if you wanted to go further and make things more elegant, then a [NamedServiceAttribute("A")] on the implementation/class could be found by the code in this extension, and it'd work just as well. To be even more fair, Reflection is slow, so an optimization may be in order, but honestly that's something the DI engine should've been helping with. Speed and simplicity are each grand contributors to TCO.

All in all, there's no need for an explicit factory, because "finding a named service" is such a reusable concept, and factory classes don't scale as a solution. And a Func<> seems fine, but a switch block is so bleh, and again, you'll be writing Funcs as often as you'd be writing Factories. Start simple, reusable, with less code, and if that turns out not to do it for ya, then go complex.


Necromancing.
I think people here are reinventing the wheel - and badly, if I may say so ...
If you want to register a component by key, just use a dictionary:

System.Collections.Generic.Dictionary<string, IConnectionFactory> dict = 
    new System.Collections.Generic.Dictionary<string, IConnectionFactory>(
        System.StringComparer.OrdinalIgnoreCase);

dict.Add("ReadDB", new ConnectionFactory("connectionString1"));
dict.Add("WriteDB", new ConnectionFactory("connectionString2"));
dict.Add("TestDB", new ConnectionFactory("connectionString3"));
dict.Add("Analytics", new ConnectionFactory("connectionString4"));
dict.Add("LogDB", new ConnectionFactory("connectionString5"));

And then register the dictionary with the service-collection:

services.AddSingleton<System.Collections.Generic.Dictionary<string, IConnectionFactory>>(dict);

if you then are unwilling to get the dictionary and access it by key, you can hide the dictionary by adding an additional key-lookup-method to the service-collection:
(the use of delegate/closure should give a prospective maintainer a chance at understanding what's going on - the arrow-notation is a bit cryptic)

services.AddTransient<Func<string, IConnectionFactory>>(
    delegate (IServiceProvider sp)
    {
        return
            delegate (string key)
            {
                System.Collections.Generic.Dictionary<string, IConnectionFactory> dbs = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService
 <System.Collections.Generic.Dictionary<string, IConnectionFactory>>(sp);

                if (dbs.ContainsKey(key))
                    return dbs[key];

                throw new System.Collections.Generic.KeyNotFoundException(key); // or maybe return null, up to you
            };
    });

Now you can access your types with either

IConnectionFactory logDB = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<Func<string, IConnectionFactory>>(serviceProvider)("LogDB");
logDB.Connection

or

System.Collections.Generic.Dictionary<string, IConnectionFactory> dbs = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<System.Collections.Generic.Dictionary<string, IConnectionFactory>>(serviceProvider);
dbs["logDB"].Connection

As we can see, the first one is just completely superfluous, because you can also do exactly that with a dictionary, without requiring closures and AddTransient (and if you use VB, not even the braces will be different):

IConnectionFactory logDB = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService<System.Collections.Generic.Dictionary<string, IConnectionFactory>>(serviceProvider)["logDB"];
logDB.Connection

(simpler is better - you might want to use it as extension method though)

Of course, if you don't like the dictionary, you can also outfit your interface with a property Name (or whatever), and look that up by key:

services.AddSingleton<IConnectionFactory>(new ConnectionFactory("ReadDB"));
services.AddSingleton<IConnectionFactory>(new ConnectionFactory("WriteDB"));
services.AddSingleton<IConnectionFactory>(new ConnectionFactory("TestDB"));
services.AddSingleton<IConnectionFactory>(new ConnectionFactory("Analytics"));
services.AddSingleton<IConnectionFactory>(new ConnectionFactory("LogDB"));



// https://stackoverflow.com/questions/39174989/how-to-register-multiple-implementations-of-the-same-interface-in-asp-net-core
services.AddTransient<Func<string, IConnectionFactory>>(
    delegate(IServiceProvider sp)
    {
        return
            delegate(string key)
            {
                System.Collections.Generic.IEnumerable<IConnectionFactory> svs = 
                    sp.GetServices<IConnectionFactory>();
                
                foreach (IConnectionFactory thisService in svs)
                {
                    if (key.Equals(thisService.Name, StringComparison.OrdinalIgnoreCase))
                        return thisService;
                }
    
                return null;
            };
    });

But that requires changing your interface to accommodate the property, and looping through a lot of elements should be much slower than an associative-array lookup (dictionary).
It's nice to know that it can be done without dictionary, though.

These are just my $0.05


Apparently, you can just inject IEnumerable of your service interface! And then find the instance that you want using LINQ.

My example is for the AWS SNS service but you can do the same for any injected service really.

Startup

foreach (string snsRegion in Configuration["SNSRegions"].Split(',', StringSplitOptions.RemoveEmptyEntries))
{
    services.AddAWSService<IAmazonSimpleNotificationService>(
        string.IsNullOrEmpty(snsRegion) ? null :
        new AWSOptions()
        {
            Region = RegionEndpoint.GetBySystemName(snsRegion)
        }
    );
}

services.AddSingleton<ISNSFactory, SNSFactory>();

services.Configure<SNSConfig>(Configuration);

SNSConfig

public class SNSConfig
{
    public string SNSDefaultRegion { get; set; }
    public string SNSSMSRegion { get; set; }
}

appsettings.json

  "SNSRegions": "ap-south-1,us-west-2",
  "SNSDefaultRegion": "ap-south-1",
  "SNSSMSRegion": "us-west-2",

SNS Factory

public class SNSFactory : ISNSFactory
{
    private readonly SNSConfig _snsConfig;
    private readonly IEnumerable<IAmazonSimpleNotificationService> _snsServices;

    public SNSFactory(
        IOptions<SNSConfig> snsConfig,
        IEnumerable<IAmazonSimpleNotificationService> snsServices
        )
    {
        _snsConfig = snsConfig.Value;
        _snsServices = snsServices;
    }

    public IAmazonSimpleNotificationService ForDefault()
    {
        return GetSNS(_snsConfig.SNSDefaultRegion);
    }

    public IAmazonSimpleNotificationService ForSMS()
    {
        return GetSNS(_snsConfig.SNSSMSRegion);
    }

    private IAmazonSimpleNotificationService GetSNS(string region)
    {
        return GetSNS(RegionEndpoint.GetBySystemName(region));
    }

    private IAmazonSimpleNotificationService GetSNS(RegionEndpoint region)
    {
        IAmazonSimpleNotificationService service = _snsServices.FirstOrDefault(sns => sns.Config.RegionEndpoint == region);

        if (service == null)
        {
            throw new Exception($"No SNS service registered for region: {region}");
        }

        return service;
    }
}

public interface ISNSFactory
{
    IAmazonSimpleNotificationService ForDefault();

    IAmazonSimpleNotificationService ForSMS();
}

Now you can get the SNS service for the region that you want in your custom service or controller

public class SmsSender : ISmsSender
{
    private readonly IAmazonSimpleNotificationService _sns;

    public SmsSender(ISNSFactory snsFactory)
    {
        _sns = snsFactory.ForSMS();
    }

    .......
 }

public class DeviceController : Controller
{
    private readonly IAmazonSimpleNotificationService _sns;

    public DeviceController(ISNSFactory snsFactory)
    {
        _sns = snsFactory.ForDefault();
    }

     .........
}

Most of the answers here violate the single responsibility principle (a service class should not resolve dependencies itself) and/or use the service locator anti-pattern.

Another option to avoid these problems is to:

  • use an additional generic type parameter on the interface or a new interface implementing the non generic interface,
  • implement an adapter/interceptor class to add the marker type and then
  • use the generic type as “name”

I’ve written an article with more details: Dependency Injection in .NET: A way to work around missing named registrations


My solution for what it's worth... considered switching to Castle Windsor as can't say I liked any of the solutions above. Sorry!!

public interface IStage<out T> : IStage { }

public interface IStage {
      void DoSomething();
}

Create your various implementations

public class YourClassA : IStage<YouClassA> { 
    public void DoSomething() 
    {
        ...TODO
    }
}

public class YourClassB : IStage<YourClassB> { .....etc. }

Registration

services.AddTransient<IStage<YourClassA>, YourClassA>()
services.AddTransient<IStage<YourClassB>, YourClassB>()

Constructor and instance usage...

public class Whatever
{
   private IStage ClassA { get; }

   public Whatever(IStage<YourClassA> yourClassA)
   {
         ClassA = yourClassA;
   }

   public void SomeWhateverMethod()
   {
        ClassA.DoSomething();
        .....
   }

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to asp.net-core

dotnet ef not found in .NET Core 3 How to use Bootstrap 4 in ASP.NET Core ASP.NET Core - Swashbuckle not creating swagger.json file Getting value from appsettings.json in .net core .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Automatically set appsettings.json for dev and release environments in asp.net core? Get ConnectionString from appsettings.json instead of being hardcoded in .NET Core 2.0 App Unable to create migrations after upgrading to ASP.NET Core 2.0 EF Core add-migration Build Failed ASP.NET Core form POST results in a HTTP 415 Unsupported Media Type response

Examples related to asp.net-core-mvc

Getting value from appsettings.json in .net core Unable to create migrations after upgrading to ASP.NET Core 2.0 ASP.NET Core form POST results in a HTTP 415 Unsupported Media Type response ASP.NET Core Get Json Array using IConfiguration ASP.NET Core Dependency Injection error: Unable to resolve service for type while attempting to activate How do I access Configuration in any class in ASP.NET Core? How to register multiple implementations of the same interface in Asp.Net Core? ASP.NET Core Identity - get current user How to get current url in view in asp.net core 1.0 How to return HTTP 500 from ASP.NET Core RC2 Web Api?

Examples related to coreclr

Is it possible to make desktop GUI application in .NET Core? How to register multiple implementations of the same interface in Asp.Net Core?