Learn ASP.NET Core 3.0 : MVC, Razor Pages, Web API, Entity Framework Core, and Blazor.
Microsoft's official documentation can be found here. Looking for professional online training courses? Next weekend batches are starting in November 2019. More details here.

Multiple implementations of an interface in ASP.NET Core DI container

If you worked with ASP.NET Core before chances are you used ASP.NET Core's dependency injection features. Most commonly you register a single implementation of an interface as a service type. However, at times you may want to register multiple implementations of an interface as service types. In this article you learn how to accomplish the task.

Let's first understand what we are trying to accomplish.

Suppose you have an interface as shown below:

public interface IHelloService
{
    string SayHello();
}

The IHelloService interface contains just a single method named SayHello().

Let's further assume that you have three implementations of IHelloService with you as outlined below:

public class HelloA:IHelloService
{
    public string SayHello()
    {
        return "Hello World!";
    }
}


public class HelloB : IHelloService
{
    public string SayHello()
    {
        return "Hello Galaxy!";
    }
}


public class HelloC : IHelloService
{
    public string SayHello()
    {
        return "Hello Universe!";
    }
}

The three implementations namely HelloA, HelloB, and HelloC simply return three different strings to the caller - Hello World!, Hello Galaxy!, and Hello Universe!.

How do you register these three concrete types with the ASP.NET Core's DI container?

One of the ways is this :

services.AddScoped<HelloA>();
services.AddScoped<HelloB>();
services.AddScoped<HelloC>();

In your ConfigureServices() you add the above code and register the concrete types HelloA, HelloB, and HelloC with the DI container. Although all of them implement IHelloService, while registering them they are registered as independent concrete types.

To grab one or more implementations of IHelloService you can use constructor injection like this :

public IndexModel(HelloA hello1, HelloB hello2, 
HelloC hello3)
{
    string msg1 = hello1.SayHello();
    string msg2 = hello2.SayHello();
    string msg3 = hello3.SayHello();
}

The above code shows a constructor of Index razor page. The constructor has three parameters - one for each concrete type. In this case the DI container will supply the respective types as expected and the three string variables will hold - Hello World!, Hello Galaxy!, and Hello Universe! respectively.

So far so good.

Now, change the way you registered the services in the ConfigureServices().

services.AddScoped<IHelloService, HelloA>();
services.AddScoped<IHelloService, HelloB>();
services.AddScoped<IHelloService, HelloC>();

Note that AddScoped() now registers multiple implementations of IHelloService. To accommodate this change you also modify the constructor as shown below:

public IndexModel(IHelloService hello1, IHelloService hello2, 
IHelloService hello3)
{
    string msg1 = hello1.SayHello();
    string msg2 = hello2.SayHello();
    string msg3 = hello3.SayHello();
}

What's the outcome?

You will find that all the string variables contain Hello Universe! This is because DI container injects only HelloC objects in the constructor since it's the last implementation of IHelloService registered in the ConfigureServices().

To inject all the implementations of IHelloServices interface you need to modify the constructor like this:

public IndexModel(IEnumerable<IHelloService> hello)
{
    foreach(var obj in hello)
    {
        string msg = obj.SayHello();
    }
}

As you can see, the constructor now takes an IEnumerable<IHelloService>. This way all the registered implementations of IHelloService are injected into the constructor. Inside, you can loop through the supplied implementations and invoke SayHello() on each. This time you will find that SayHello() correctly returns Hello World!, Hello Galaxy!, and Hello Universe! during the corresponding iterations. You can also check the type of obj to decide whether to use that implementation of IHelloService or not.

That's it for now! Keep coding!!


Bipin Joshi is an independent software consultant, trainer, author, yoga mentor, and meditation teacher. He has been programming, meditating, and teaching for 24+ years. He conducts instructor-led online training courses in ASP.NET family of technologies for individuals and small groups. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Ajapa Yoga to interested individuals. To know more about him click here.

Get article updates : Facebook  Twitter  LinkedIn

Posted On : 27 May 2019


Tags : ASP.NET ASP.NET Core MVC C# Visual Studio


Subscribe to our newsletter

Get monthly email updates about new articles, tutorials, code samples, and how-tos getting added to our knowledge base.

  

Receive Weekly Updates