ASP.NET Core has built-in support for dependency injection. However, multiple implementations of an interface in ASP.NET Core is tricky. In this article, I’m going to explain two approaches through which how we can dynamically select a service from such an implementation in ASP.NET Core.
I have used the below tools for preparing this tutorial
- VS 2019 Community Edition 16.4.5
- ASP.NET Core 3.1
- Swagger for testing and documenting the API
The two approaches which we are going to discuss over here are below
- Implement the interface using the func delegate with key
- Implement the interface using IEnumberable collection
Using the delegate func
Create a simple Web API project and follow the steps below
Introduce one interface called IShoppingCart
public interface IShoppingCart {
object GetCart();
}
Introduce three implementation classes as below- three different classes where we have implemented the same interface.
public class ShoppingCartFlipCart: IShoppingCart {
public object GetCart() {
return $ " Items from FlipCart";
}
}
public class ShoppingCartAmazon: IShoppingCart {
public object GetCart() {
return $ "grab items from Amazone";
}
}
public class ShoppingCartEBay: IShoppingCart {
public object GetCart() {
return $ "Items from ebay";
}
}
Introduce an enum –we will be using while resolving and injecting the interface
public enum Carts {
Amazon,
Flipcart,
Ebay
}
ASP.NET Core has built-in support for dependency injection. However, multiple implementations of an interface in ASP.NET Core is tricky. In this article, I’m going to explain two approaches through which how we can dynamically select a service from such an implementation in ASP.NET Core.
I have used the below tools for preparing this tutorial
- VS 2019 Community Edition 16.4.5
- ASP.NET Core 3.1
- Swagger for testing and documenting the API
The two approaches which we are going to discuss over here are below
- Implement the interface using the func delegate with key
- Implement the interface using IEnumberable collection
Using the delegate func
Create a simple Web API project and follow the steps below
Introduce one interface called IShoppingCart
public interface IShoppingCart {
object GetCart();
}
Introduce three implementation classes as below- three different classes where we have implemented the same interface.
public class ShoppingCartFlipCart: IShoppingCart {
public object GetCart() {
return $ " Items from FlipCart";
}
}
public class ShoppingCartAmazon: IShoppingCart {
public object GetCart() {
return $ "grab items from Amazone";
}
}
public class ShoppingCartEBay: IShoppingCart {
public object GetCart() {
return $ "Items from ebay";
}
}
Introduce an enum –we will be using while resolving and injecting the interface
public enum Carts {
Amazon,
Flipcart,
Ebay
}
Introduce another interface as below
public interface IShoppingCartRepository {
object GetCart();
}
Introduce a class where I have implemented the Interface created in step 4
public class ShoppingCartRepository: IShoppingCartRepository {
private readonly Func < Carts, IShoppingCart > _shoppingCart;
public ShoppingCartRepository(Func < Carts, IShoppingCart > shoppingCart) {
this._shoppingCart = shoppingCart;
}
public object GetCart() {
var obj = this._shoppingCart(Carts.Amazon);
return obj.GetCart();
}
}
Here I have used a func delegate Func<Carts, IShoppingCart>, this will be registered to container in Startup.cs class.
Let us go ahead and configure these classes and interface into dependency container. In order register the interface, we need to go the Starup.cs class.
In Startup.cs class, we have two methods,
public void ConfigureServices(IServiceCollection services) //this method gets called by runtime. Use this method to add services to the container.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) //this method gets called by runtime. Use this method to configure the Http request pipeline
I may come up with an article on Startup.cs. Please refer the below links to understand the Startup.cs class and the methods belonging to this class.
In ASP.NET Core 6, Startup.cs will not be created by default.
Without any delay, let us jump into Startup.cs class
Let us register the interface and classes to the container
public void ConfigureServices(IServiceCollection services) {
services.AddScoped < IShoppingCartRepository, ShoppingCartRepository > ();
services.AddTransient < ShoppingCartEBay > ();
services.AddTransient < ShoppingCartFlipCart > ();
services.AddTransient < ShoppingCartAmazone > ();
services.AddTransient < Func < Carts, IShoppingCart >> (serviceProvider => key => {
switch (key) {
case Carts.Amazon:
return serviceProvider.GetService < ShoppingCartAmazone > ();
case Carts.Flipcart:
return serviceProvider.GetService < ShoppingCartEBay > ();
case Carts.Ebay:
return serviceProvider.GetService < ShoppingCartFlipCart > ();
default:
throw new NotImplementedException();
}
});
services.AddControllers();
//Swashbuckle.AspNetCore needs to be installed from NuGet
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new OpenApiInfo {
Title = "Interface with Multiple Implementations",
Version = "v1",
Description = "Same Interface with Multiple Implementation in ASP.NET Core 3.1",
Contact = new OpenApiContact {
Name = "Prasad Raveendran",
Email = string.Empty,
Url = new Uri("https://www.c-sharpcorner.com/members/prasad-nair3")
}
});
});
}
Now, let's go ahead and add the swaggerUI to the request pipeline via the method Configure
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
});
app.UseSwagger();
app.UseSwaggerUI(sw => {
sw.SwaggerEndpoint("/swagger/v1/swagger.json", "API V1.0");
});
}
Add a Controller called MultipleController.cs
[Route("api/[controller]")]
[ApiController]
public class MultipleController: ControllerBase {
private IShoppingCartRepository _shoppingCartRepository;
public MultipleController(IShoppingCartRepository shoppingCartRepository) {
this._shoppingCartRepository = shoppingCartRepository;
}
[HttpGet]
public IEnumerable < string > GetAmazoneProducts() {
return new string[] {
"Cart",
this._shoppingCartRepository.GetCart().ToString()
};
}
}
Go ahead and run the application, Swagger UI will be displayed on the browser- now you are good to go and debug the code.
If you execute the api - https://localhost:1234555/api/Multiple
Port number will be varied.
You will be getting the response as below
[
"Cart",
"grab items from Amazone"
]
Which is nothing but the response from the class ShoppingCartAmazon.cs
Using IEnumerable
Create the below enum as below
public enum InstanceEnum {
First,
Second
}
Create the below interface as below
public interface IInstance {
InstanceEnum GetType();
string GetDetails();
}
Let us create the below implementation classes
FirstInstance class which has been implemented by the interface IInstance
public class FirstInstance: IInstance {
public string GetDetails() {
return "From FirstInstance";
}
InstanceEnum IInstance.GetType() {
return InstanceEnum.First;
}
}
SecondInstance class which has been implemented by interface IInstance
public class SecondInstance: IInstance {
public string GetDetails() {
return "From Second Instance";
}
InstanceEnum IInstance.GetType() {
return InstanceEnum.Second;
}
}
Now let us go ahead and register these two classes into the container using Startup.cs
public void ConfigureServices(IServiceCollection services) {
services.AddSingleton < IInstance, FirstInstance > ();
services.AddSingleton < IInstance, SecondInstance > ();
services.AddControllers();
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo {
Title = "Multiple Implementation using IEnumberable",
});
});
}
Now add the swagger to the pipeline
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
});
app.UseSwagger();
app.UseSwaggerUI(sw => {
sw.SwaggerEndpoint("/swagger/v1/swagger.json", "API V1.0");
});
}
Now create a control and inject the interface using the IEnumberable as below
[Route("api/[controller]")]
[ApiController]
public class MultipleController: ControllerBase {
private IInstance _instance;
public MultipleController(IEnumerable < IInstance > instances) {
_instance = instances.Where(i => i.GetType() == InstanceEnum.First).FirstOrDefault();
}
[HttpGet]
public string GetFirstInstance() {
return _instance.GetDetails();
}
}
Let us go ahead and build the project, and run,
URL : http://localhost:123455/api/Multiple
Port number will be varied based on the workstation
Output will be as below
From FirstInstance
Summary
Here we have gone through the basic understanding on multiple implementations of an interface in ASP.NET Core. Thanks for watching the article. Please do comment your feedbacks.
Introduce another interface as below
public interface IShoppingCartRepository {
object GetCart();
}
Introduce a class where I have implemented the Interface created in step 4
public class ShoppingCartRepository: IShoppingCartRepository {
private readonly Func < Carts, IShoppingCart > _shoppingCart;
public ShoppingCartRepository(Func < Carts, IShoppingCart > shoppingCart) {
this._shoppingCart = shoppingCart;
}
public object GetCart() {
var obj = this._shoppingCart(Carts.Amazon);
return obj.GetCart();
}
}
Here I have used a func delegate Func<Carts, IShoppingCart>, this will be registered to container in Startup.cs class.
Let us go ahead and configure these classes and interface into dependency container. In order register the interface, we need to go the Starup.cs class.
In Startup.cs class, we have two methods,
public void ConfigureServices(IServiceCollection services) //this method gets called by runtime. Use this method to add services to the container.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) //this method gets called by runtime. Use this method to configure the Http request pipeline
I may come up with an article on Startup.cs. Please refer the below links to understand the Startup.cs class and the methods belonging to this class.
In ASP.NET Core 6, Startup.cs will not be created by default.
Without any delay, let us jump into Startup.cs class
Let us register the interface and classes to the container
public void ConfigureServices(IServiceCollection services) {
services.AddScoped < IShoppingCartRepository, ShoppingCartRepository > ();
services.AddTransient < ShoppingCartEBay > ();
services.AddTransient < ShoppingCartFlipCart > ();
services.AddTransient < ShoppingCartAmazone > ();
services.AddTransient < Func < Carts, IShoppingCart >> (serviceProvider => key => {
switch (key) {
case Carts.Amazon:
return serviceProvider.GetService < ShoppingCartAmazone > ();
case Carts.Flipcart:
return serviceProvider.GetService < ShoppingCartEBay > ();
case Carts.Ebay:
return serviceProvider.GetService < ShoppingCartFlipCart > ();
default:
throw new NotImplementedException();
}
});
services.AddControllers();
//Swashbuckle.AspNetCore needs to be installed from NuGet
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new OpenApiInfo {
Title = "Interface with Multiple Implementations",
Version = "v1",
Description = "Same Interface with Multiple Implementation in ASP.NET Core 3.1",
Contact = new OpenApiContact {
Name = "Prasad Raveendran",
Email = string.Empty,
Url = new Uri("https://www.c-sharpcorner.com/members/prasad-nair3")
}
});
});
}
Now, let's go ahead and add the swaggerUI to the request pipeline via the method Configure
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
});
app.UseSwagger();
app.UseSwaggerUI(sw => {
sw.SwaggerEndpoint("/swagger/v1/swagger.json", "API V1.0");
});
}
Add a Controller called MultipleController.cs
[Route("api/[controller]")]
[ApiController]
public class MultipleController: ControllerBase {
private IShoppingCartRepository _shoppingCartRepository;
public MultipleController(IShoppingCartRepository shoppingCartRepository) {
this._shoppingCartRepository = shoppingCartRepository;
}
[HttpGet]
public IEnumerable < string > GetAmazoneProducts() {
return new string[] {
"Cart",
this._shoppingCartRepository.GetCart().ToString()
};
}
}
Go ahead and run the application, Swagger UI will be displayed on the browser- now you are good to go and debug the code.
If you execute the api - https://localhost:1234555/api/Multiple
Port number will be varied.
You will be getting the response as below
[
"Cart",
"grab items from Amazone"
]
Which is nothing but the response from the class ShoppingCartAmazon.cs
Using IEnumerable
Create the below enum as below
public enum InstanceEnum {
First,
Second
}
Create the below interface as below
public interface IInstance {
InstanceEnum GetType();
string GetDetails();
}
Let us create the below implementation classes
FirstInstance class which has been implemented by the interface IInstance
public class FirstInstance: IInstance {
public string GetDetails() {
return "From FirstInstance";
}
InstanceEnum IInstance.GetType() {
return InstanceEnum.First;
}
}
SecondInstance class which has been implemented by interface IInstance
public class SecondInstance: IInstance {
public string GetDetails() {
return "From Second Instance";
}
InstanceEnum IInstance.GetType() {
return InstanceEnum.Second;
}
}
Now let us go ahead and register these two classes into the container using Startup.cs
public void ConfigureServices(IServiceCollection services) {
services.AddSingleton < IInstance, FirstInstance > ();
services.AddSingleton < IInstance, SecondInstance > ();
services.AddControllers();
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo {
Title = "Multiple Implementation using IEnumberable",
});
});
}
Now add the swagger to the pipeline
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
});
app.UseSwagger();
app.UseSwaggerUI(sw => {
sw.SwaggerEndpoint("/swagger/v1/swagger.json", "API V1.0");
});
}
Now create a control and inject the interface using the IEnumberable as below
[Route("api/[controller]")]
[ApiController]
public class MultipleController: ControllerBase {
private IInstance _instance;
public MultipleController(IEnumerable < IInstance > instances) {
_instance = instances.Where(i => i.GetType() == InstanceEnum.First).FirstOrDefault();
}
[HttpGet]
public string GetFirstInstance() {
return _instance.GetDetails();
}
}
Let us go ahead and build the project, and run,
URL : http://localhost:123455/api/Multiple
Port number will be varied based on the workstation
Output will be as below
From FirstInstance
Summary
Here we have gone through the basic understanding on multiple implementations of an interface in ASP.NET Core. Thanks for watching the article. Please do comment your feedbacks.