Dependency Injection in Asp.Net Core

|
| By Webner

Introduction:

The ASP.NET Core provides the idea of Dependency Injection without having to install any external injection containers and resolve the dependencies. My experience with ASP.NET Core is connecting some applications related to the use of such templates for dependencies.

The whole development ideology using dependency injection is based on these principles:

  • Effectively designing services and their dependencies.
  • Preventing multi-threading issues.
  • Preventing memory-leaks.
  • Preventing potential bugs.

Constructor Injection:

Constructor injection is used to declare and obtain dependencies of service on the service construction. we added services as a constructor parameter, and at the runtime resolves the service from the service container. Services are defined using interfaces.

HomeController

public class HomeController : Controller
{
private IEmployeeRepository _employeeRepository;
// Inject IEmployeeRepository using Constructor Injection
public HomeController(IEmployeeRepository employeeRepository)
{
_employeeRepository = employeeRepository;
}
// Retrieve employee name and return
public string Index()
{
return _employeeRepository.GetEmployee(1).Name;
}
}

IEmployeeRepository:

public interface IEmployeeRepository
{
 Employee GetEmployee(int Id);
}

Points to Remember:

  • For retrieving Employee data HomeController is dependent on IEmployeeRepository.
  • Instead of the HomeController create a new instance of an implementation of IEmployeeRepository, Using the constructor, we are injecting the IEmployeeRepository instance into the HomeController.
  • This is known as constructor injection, as we are using the constructor to inject the dependency.
  • We just assign the injected dependency to a read-only field. This is good practice.
  • At this point, if we run the project we get these error
    InvalidOperationException: Unable to resolve service for type ‘Employee_Management.Models.IEmployeeRepository’ while attempting to activate ‘Employee_Management.Controllers.HomeController’.
    This is because if someone requests an object, the ASP .NET dependency injection container does not know which object instance to provide that implements IEmployeeRepository.
  • IEmployeeRepository has several implementations. At this moment we only have one implementation in our project and that is MockEmployeeRepository.
  • MockEmployeeRepository works with the in-memory employee mock data.
  • To fix the InvalidOperationException error, we need to register the MockEmployeeRepository class with the dependency injection container in the ASP.NET core project.
  • We do this in ConfigureServices() method which is provided in Startup class.

Registering Services with the Dependency Injection Container:

To fix the InvalidOperationException error, let’s register the MockEmployeeRepository class with the Dependency Injection container using AddSingleton() method as shown below. With this code, if someone asks for IEmployeeRepository, an instance of MockEmployeeRepository will be provided.

AddSingleton() – AddSingleton() method creates a Singleton service and is created when it is first requested. A single instance is used by all the subsequent requests. A single service is created only one time per application or that a single instance is used throughout the application lifetime.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddSingleton<IEmployeeRepository, MockEmployeeRepository>();
}

At this point, you might be thinking, why do we have to do all this and why we can’t simply create an instance of MockEmployeeRepository class in the HomeController using the new keyword as shown below.

public class HomeController : Controller
{
    private readonly IEmployeeRepository _employeeRepository;

    // Inject IEmployeeRepository using Constructor Injection
    public HomeController(IEmployeeRepository employeeRepository)
    {
        _employeeRepository = new MockEmployeeRepository();
    }

    // Retrieve employee name and return
    public string Index()
    {
        return _employeeRepository.GetEmployee(1).Name;
    }
}

Well, this makes HomeController tightly coupled to MockEmployeeRepository. Later if we want to provide a new implementation for IEmployeeRepository or if we want to use that new implementation instead of MockEmployeeRepository, we will have to change the code in HomeController. You might be thinking, this is just one line of code change, so it is not too difficult to do.

Now the question arises, what if we have used this MockEmployeeRepository in 100 other controllers in our application?
We need to change/update all the 100 controllers. This is too difficult and also error-prone.

So in short, to create instances of dependencies using the new keyword creates tight coupling and as a result, your application would be difficult to change. With dependency injection, we will not have tight coupling.

With dependency injection, if we’ve used MockEmployeeRepository in 100 other controllers in our application, if we would like to swap it out with a different implementation, we are required to change in one line of code in Startup.cs. Notice, we are now using DatabaseEmployeeRepository rather than MockEmployeeRepository.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddSingleton<IEmployeeRepository, DatabaseEmployeeRepository>();
}

How does ASP .NET core provide dependency injection

The ASP.NET Core provides the idea of Dependency Injection without having to install any external injection containers and resolve the dependencies.

What are the principles for dependency injection?

- Effectively designing services and their dependencies.
- Preventing multi-threading issues.
- Preventing memory-leaks.
- Preventing potential bugs.

What is contructor injection?

Constructor injection is used to declare and obtain dependencies of service on the service construction.

Leave a Reply

Your email address will not be published. Required fields are marked *