Consider a scenario where you want to fetch all the categories from the database and want to show that in the UI layer. So, you will create a service, i.e., a Web API which will be called by the UI layer. Now, in API, we need to create one GET method which will call the repository and the repository talks with the database. In order to call the repository, we need to create an instance of the same in API GET method, which means, it’s mandatory to create an instance of the repository for API. We can say the instance of the repository is the dependency of API. Now, let’s see how we can inject this dependency in our core Web API.
Open Visual Studio and create a new project
Select API as template and press OK.
As we are going to fetch the categories, let’s create a category model which has two fields - CategoryId and CategoryName.
namespace DIinCore
{
public class Category
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
}
Create an interface of repository having GetCategories method which returns the list of category object.
using System.Collections.Generic;
namespace DIinCore
{
public interface ICategoryRepository
{
List<Category> GetCategories();
}
}
Implement the preceding interface and return some sample data. As our target is to understand dependency injection, here, we are not going to fetch the data from database rather returning hard coded ones.
using System.Collections.Generic;
namespace DIinCore
{
public class CategoryRepository : ICategoryRepository
{
public List<Category> GetCategories()
{
List<Category> categories = new List<Category>();
Category category = new Category() { CategoryId = 1, CategoryName = "Category1" };
categories.Add(category);
category = new Category() { CategoryId = 2, CategoryName = "Category2" };
categories.Add(category);
return categories;
}
}
}
Assume that we are not aware of the dependency injection. Then, how will we expose the GET method from API? We used to create an instance of CategoryRepository and call the GetCategories method using that instance. So tomorrow, if there is a change in CategoryRepository it will directly affect the GET method of API as it is tightly coupled with that.
[HttpGet]
public async Task<IActionResult> Get()
{
CategoryRepository categoryRepository = new CategoryRepository();
List<Category> categories = categoryRepository.GetCategories();
return Ok(categories);
}
With the .NET Framework, we used to use containers like LightInject, NInject, Unity etc. But in .NET Core, Microsoft has provided an in-built container. We need to add the namespace, i.e., Microsoft.Extension.DependencyInjection.
So, in the startup class, inside the ConfigureServices method, we need to add our dependency into the service collection which will dynamically inject whenever and wherever we want in the project. Also, we can mention which kind of instance we want to inject - the lifetime of our instance.
Transient
It creates an instance each time they are requested and are never shared. It is used mainly for lightweight stateless services.
Singleton
This creates only single instances which are shared among all components that require it.
Scoped
It creates an instance once per scope which is created on every request to the application.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace DIinCore
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
//services.AddTransient<ICategoryRepository, CategoryRepository>();
services.AddSingleton<ICategoryRepository, CategoryRepository>();
//services.AddScoped<ICategoryRepository, CategoryRepository>();
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
So far, we have added our dependency to the collection. Now, it’s time to inject where we need it, i.e., in the Web API. Our GET method is inside the CategoryController and we want an instance of categoryrepository. So, let’s create a constructor of CategoryController which expects the type of ICategoryRepository. From this parameterized constructor, set the private property of type ICategoryRepository which will be used to call GetCategories from the GET method.
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace DIinCore.Controllers
{
[Route("api/Category")]
public class CategoryController : Controller
{
private ICategoryRepository categoryRepository { get; set; }
public CategoryController(ICategoryRepository categoryRepository)
{
this.categoryRepository = categoryRepository;
}
[HttpGet]
public async Task<IActionResult> Get()
{
List<Category> categories = categoryRepository.GetCategories();
return Ok(categories);
}
}
}
Run the application and we will be able to see the result of the GET method of CategoryController. Now, even though we haven’t created an instance of CategoryRepository which is expected by CategoryController, we are able to call the GET method successfully. The instance of CategoryRepository has been resolved dynamically, i.e., our Dependency Injection.
You can download the sample code from here.