Overview of Dependency Injection in ASP.NET Core
A software developer composes a ton of code that is firmly coupled; and when unpredictability develops, the code will in the end crumble into spaghetti code; as it were, the application configuration being a terrible outline.
Reliance Injection(DI) is an example where items are not in charge of making their own conditions. Reliance Injection is an approach to expel hard-coded conditions among items, making it simpler to supplant a question's conditions, either to test (utilizing mock protests in unit test) or to change run-time conduct.
Before understanding Dependency Injection, we ought to be acquainted with the two ideas of Object Oriented Programming - tight coupling and free coupling. How about we see every, one by one.
Tight Coupling
At the point when a class is subject to a solid reliance, it is said to be firmly coupled to that class. A firmly coupled protest is reliant on another question; that implies transforming one question in a firmly coupled application frequently obliges changes to various different items. It is not troublesome when an application is little but rather in a venture level application, it is excessively troublesome, making it impossible to roll out the improvements.
Loose Coupling
It implies two objects are free and a protest can utilize another question without being reliant on it. It is a plan objective that looks to decrease the between conditions among parts of a framework with the objective of lessening the hazard that adjustments in one segment will require changes in some other segment.
Presently to put it plainly, Dependency Injection is an example that makes questions approximately coupled rather than firmly coupled. When we are planned classes with DI, they are all the more approximately coupled in light of the fact that they don't have immediate, hard-coded dependencies on their collaborators. This takes after the Dependency Inversion Principle(DIP).
There are three types of Dependency Injections:
- Constructor Dependency Injection
- Setter Dependency Injection
- Interface Dependency Injection
Dependency Inversion Principle(DIP)
It is the fifth principle of SOLID where "D" remains for Dependency Inversion Principle. Its fundamental objective is decoupling programming modules, as it were programming configuration ought to be approximately coupled rather than firmly coupled. The principle states:
- Abnormal state modules ought not rely on low-level modules. Both ought to rely on abstractions.
- Abstractions ought not rely on points of interest. Points of interest ought to rely on abstractions.
To put it plainly, the larger amount module characterizes an interface and lower-level module executes that interface. To clarify this sentence we utilize a genuine case.
Assume you are perched around your work area. Your work area has a few devices, similar to your advancement machine (LCD Monitor or Laptop) and cell phone. The LCD Monitor has a link that associates from the electric port (power link) and the same as the cell phone that additionally has a charging link that likewise interfaces with an electric port. You could see that both gadgets associate from the electric port so the question happens of who characterized the port, your gadget or the link? You will state that the gadgets characterize the port, at the end of the day we don't buy gadgets contingent upon port while the port is composed reliant on gadgets and the link is only an interface that associates both gadgets and the port so you could state that an abnormal state module doesn't rely on upon the low-level module however both ought to be subject to abstraction.
Inversion of Control (IoC) Pattern
In pratice, an application is condescended with many classes. So when we utilize DI with these classes then these classes are asking for their dependecies by means of their constructor that is the reason it's useful to have a class committed to making these classes with their related dependencies. These classes are alluded to as containers, or all the more particularly, Inversion of Control (IoC) containers or Dependency Injection (DI) containers.
The Inversion of Control (IoC) containers is a processing plant that is reponsible for giving instance of sorts that are asked for from it. On the off chance that a given sort has pronounced that it has dependencies, and the container has been designed to give the reliance sorts, it will make the dependencies as a component of making the asked for instance. Assume an application outlined with the Strategy configuration design. There are composed interfaces and actualized with classes. The IoC container designed to such way that when application is asking for interface then it gives that interface dependencies i.e class instance, consequently class object can be given to classes without the requirement for any hard-coded object development.
ASP.NET Core and DI
The ASP.NET Core itself gives essential worked in IoC container that is spoken to by IserviceProvider interface. It bolsters constructor depedency infusion of course. ASP.NET Core utilizes DI for instantiating every one of its segments and administrations. The container is designed in ConfigureService technique for the startup.cs class as this class is section indicate application. We arrange the bulit-in and custom administrations and segments that can be utilized as a part of the whole application life cycle.
The ASP.NET Core services can be configured with the three lifetimes and registration options. They are:
- Transient – Created each time they are requested.
- Scoped – Created once per request.
- Singleton – Created the first time they are requested.
Let’s learn about the Service Lifetimes in details.
Transient:
The AddTransient strategy is utilized for the Transient lifetime alternative. This AddTransient technique is utilized to enlist benefits in IoC container and it get instantiated each time when it is gotten to. In the event that we have an administration which is utilized different places in same request, another instance would be made each time.
Assume we have a client administration which is utilized to get to client detail and client name so we make two technique for these operations. One technique is utilized as a part of activity strategy and another is utilized on view so there are two new instance make as we request for both strategies for client benefit from various part controller and view.
As this strategy get instantiated on each request that is the reason it ought to be utilized for lightweight and stateless administrations.
Now let’s create an application in Visual Studio. After creating a web application:
Now we will create an interface named IUniqueKeyProviderService which has a method signature as per following code snippet:
namespace DependencyInjectionOverview.Transient
{
public interface IUniqueKeyProviderService
{
int GetUniqueKey();
}
}
Now we will create a class named ‘UniqueKeyProviderService’ which has implementation of IUniqueKeyProviderService interface per following code snippet:
namespace DependencyInjectionOverview.Transient
{
public class UniqueKeyProviderService : IUniqueKeyProviderService
{
public int GetUniqueKey()
{
return GetHashCode();
}
}
}
Now we need to register created IUniqueKeyProviderService service with its dependencies using AddTransient option in the ConfigureServices method of the Startup class as shown in the code snippet below:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddTransient < IUniqueKeyProviderService, UniqueKeyProviderService > ();
}
Now, we consume method of the IUniqueKeyProviderService service in HomeController as shown in the code snippet below:
public class HomeController : Controller
{
private readonly IUniqueKeyProviderService uniqueKeyProviderService;
public HomeController(IUniqueKeyProviderService uniqueKeyProviderService)
{
this.uniqueKeyProviderService = uniqueKeyProviderService;
}
public IActionResult Index()
{
int model = uniqueKeyProviderService.GetUniqueKey();
return View(model);
}
.
.
Here in the above code, the controller used constructor dependency injection to inject IUniqueKeyProviderService service. Likewise we can even inject IUniqueKeyProviderService service on View to access any method of service. We will show unique Id on View so add the following mark-ups as shown in the code snippet below:
@model int
@inject DependencyInjectionOverview.Transient.IUniqueKeyProviderService uniqueKeyProviderService;
<h2>Transient LifeTime</h2>
<h4>Unique Key from service Instance created on controller: @Model</h4>
<h4>Unique Key from service Instance created on view: @uniqueKeyProviderService.GetUniqueKey()</h4>
Now let run the application and let’s see the result. The output looks like this:
Here the result in the above code snippet shows that a unique key is different from both requests which means each request creates new instance of IUniqueKeyProviderService.
Scoped:
The AddScoped strategy is utilized for the Scoped lifetime choice. This Add Scoped strategy is utilized to enlist benefits in IoC container. It gives benefit instance once per request. On the off chance that we have an administration which is utilized different places in a similar request, just single instance would be made for that.
We have the same view,controller and service. We register this IUniqueKeyProviderService service with its dependencies using AddScoped option in the ConfigureServices method of the Starup class as shown in the code snippet below:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddScoped<IUniqueKeyProviderService, UniqueKeyProviderService>();
}
Now run the application, and make twosubsequent requests and the result is like this:
As per figure above, the AddScoped creates a single instance once per request. When we make another request, then it creates another instance of the service
Singleton:
The AddSingleton strategy is utilized for the Singleton lifetime choice. This AddSingleton technique is utilized to enlist benefits in IoC container. It ptovides benefit instance the first occasion when it is requested. After that each resulting request will utilize a similar instance. On the off chance that we have an administration which is utilized numerous spots in the same or separate requests, just single instance wll be made for that.
Here too, we have same view, controller and service. We register this IUniqueKeyProviderService service with its dependencies using AddSingleton option in the ConfigureServices method of the Startup class as shown in the code snippet below:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton<IUniqueKeyProviderService, UniqueKeyProviderService>();
}
Now run the application and make two subsequent requests here too. The results are:
As per figure above, the singleton creates a single instance when requested the first time. And when we make two subsequent requests, then it uses instance of the service in both requests.
Framework-Provided Services
The ConfigureServices technique in the Startup class is in charge of characterizing the administrations the application will utilize, including stage highlights like Entity Framework Core, ASP.NET Core MVC and ASP.NET Core Identity. The elements and middleware given by ASP.NET, for example, MVC, take after a tradition of utilizing a solitary AddServiceName augmentation technique to enlist the greater part of the administrations required by that component, for example, AddDbContext, AddIdentity, AddMVC and AddAuthorization and so forth.
- AddDbContext - This method is utilized to add application DbContext to the reliance infusion.
AddIdentity - The personality administrations are added to the application in the ConfigureServices strategy.