简体   繁体   中英

How to register two implementations then get one in .Net Core dependency injection

I have parts of my code which depend on more than one implementation of the same interface, and other parts which depend on one of the implementations.

I am registering implementations like:

services.AddSingleton<MyInterface, FirstImplementation>();
services.AddSingleton<MyInterface, SecondImplementation>();

Then getting both implementations when needed like:

var implementations= serviceProvider.GetServices<MyInterface>();

My Issue is when I need one of them, I am trying the following which returns null:

var firstImplementation= serviceProvider.GetService<FirstImplementation>();

Of course I could use:

var implementations= serviceProvider.GetServices<MyInterface>();
foreach (var implementation in implementations)
{
    if (typeof(FirstImplementation) == implementation.GetType())
    {
        FirstImplementation firstImplementation = (FirstImplementation)implementation;
    }
}

But I am thinking that I can get my FirstImplementation directly somehow.

The container knows how to resolve a FirstImplementation when asked for the MyInterface , how ever is was not told how to resolve a FirstImplementation when asked specifically for a FirstImplementation .

The built-in services container is meant to serve the basic needs of the framework and most consumer applications built on it. It is bare bones and needs to be configured explicitly to behave as desired. You will need to also tell it how to get the implementations when explicitly asked for the implementations

//register implementations first
services.AddSingleton<FirstImplementation>();
services.AddSingleton<SecondImplementation>();

//register interfaces using factory that return implementation singleton
services.AddSingleton<MyInterface, FirstImplementation>(p => p.GetService<FirstImplementation>());
services.AddSingleton<MyInterface, SecondImplementation>(p => p.GetService<SecondImplementation>());

So now you can get your FirstImplementation directly and get the same instance

var firstImplementation = serviceProvider.GetService<FirstImplementation>();

Actually what you did is not a good practice, You can create two different interfaces inherited from your base interface ( MyInterface ) and then register each implementation corresponding on the proper interface, After that in the part of your code which you need specific implementation you can ask from IoC go give you back specific implementation of your significant interface:

Implementation

public interface IFirstImplementation:MyInterface {}
public interface ISecondImplementation:MyInterface {}

Registeration

services.AddTransient<IFirstImplementation, FirstImplementation>();
services.AddTransient<ISecondImplementation, SecondImplementation>();

Usage

var firstImplementation= serviceProvider.GetService<IFirstImplementation>();

Microsoft.Extensions.Dependencyinjection provides the basic needs of Dependency injection, and there's other IoC container framework available for .NET which can solve your problem. For example, you can use Autofac 's Named Services like below:

//registration method
var builder = new ContainerBuilder();
...
builder.RegisterType<FirstImplementation>().Named<MyInterface>("first");
builder.RegisterType<SecondImplementation>().Named<MyInterface>("second");

//resolve method
var firstImplementation = container.ResolveNamed<MyInterface>("first");

For more complicated scenario, you can use Keyed Services which supports resolving with an Index and attributes.

You also need to pay attention to the instance scope if uses Autofac.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM