Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 898
Yahya Hussein Avatar asked May 25 '18 05:05

Yahya Hussein


2 Answers

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>();
like image 124
Nkosi Avatar answered Sep 22 '22 21:09

Nkosi


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>();
like image 44
Mohammad Nikravesh Avatar answered Sep 21 '22 21:09

Mohammad Nikravesh