ASP.NET CORE Dependency Injection
In this tutorial will discuss what is dependency injection and how its work in net core.
Dependency Injection (DI): its a software design pattern that allows us to develop loosely coupled code. Dependency Injection is a great way to reduce tight coupling between software components. Dependency Injection also enables us to better manage future changesand other complexity in our software. The purpose of DI is to make code maintainable.
Tightly Coupling: The software components were dependent on each other in such a way that, for a small change in one component, you might need to change a lot in the dependent component. This is not good practice in software development. Simplest way to understand is when we get an instance by using a new keyword that class or service is tightly coupled.
Loosely Coupling: In this case, the software components slightly depend on each other. If we need to change one component then it will not affect much more on the dependent component. We can achieve this situation through interfaces. The classes can communicate with each other with the help of an interface. Service Lifetime
Before we can talk about how injection is done in practice, it is important to understand what is service lifetime. When we are registering our service then we need to register with the correct lifetime to define lifetime service issues or shares. The Built-in IoC container manages the lifetime of a registered service type. It automatically disposes a service instance based on the specified lifetime.
In asp.net core There are 3 options for this with the built-in DI container in ASP.NET Core:
- Singleton
- Scoped
- Transient
Singleton: means only a single instance will ever be created. That instance is shared between all components that require it. The same instance is thus always used.
Transient: instance are created every time they are requested and are never shared.
It is important to understand that if you register component A as a singleton, it cannot depend on components registered with Scoped or Transient lifetime. More generally speaking:
Service registration
ASP.NET Core is designed from scratch to support Dependency Injection. ASP.NET Core injects objects of dependency classes through constructor or method by using built-in IoC container. Registering services is done in the ConfigureServices(IServiceCollection) method in your Startup class.
public void ConfigureServices(IServiceCollection services) { services.Add(new ServiceDescriptor(typeof(ILog), new MyLogger())); // singleton services.Add(new ServiceDescriptor(typeof(ILog), typeof(MyLogger), ServiceLifetime.Transient)); // Transient services.Add(new ServiceDescriptor(typeof(ILog), typeof(MyLogger), ServiceLifetime.Scoped)); // Scoped }
ASP.NET Core framework includes extension methods for each type of lifetime; AddSingleton(), AddTransient() and AddScoped() methods for singleton, transient and scoped lifetime respectively. understand the service lifetime and registration we have created two services that will register as scoped and transient.
public void ConfigureServices(IServiceCollection services) { services.AddSingleton(); services.AddSingleton(typeof(IConfiguration)); services.AddTransient<ILogTransient, MyLoggerTransient>(); services.AddTransient(typeof(ILogTransient), typeof(MyLoggerTransient)); services.AddScoped<ILogScoped, MyLoggerScoped>(); services.AddScoped(typeof(ILogScoped), typeof(MyLoggerScoped)); }
Injection type
Constructor Injection
Once we register a service, the IoC container automatically performs constructor injection if a service type is included as a parameter in a constructor. For example, we can use ILogScoped and ILogTransient service type in any MVC controller. Consider the following example.
public class HomeController { private ILogScoped _logScoped; private ILogTransient _logTransient; public HomeController(ILogScoped logScoped, ILogTransient logTransient) { _logScoped = logScoped; _logTransient = logTransient; } }
In the above example, an IoC container will automatically pass an instance of MyLoggerScoped and MyLoggerTransient to the constructor of HomeController. We don’t need to do anything else.An IoC container will create and dispose instance based on the registered lifetime.
Action Method Injection
Sometimes we may only need dependency service type in a single action method.For this, use [FromServices] attribute with the service type parameter in the method.
public IActionResult Index([FromServices] ILogScoped logScopedService, [FromServices] ILogTransient logTransientService) { return View(); }
Property Injection
Built-in IoC containers do not support property injection. You will have to use a third party IoC container.
Get Services Manually
It is not required to include dependency services in the constructor. We can access dependent services configured with a built-in IoC container manually using the RequestServices property ofHttpContext as shown below.
var services = this.HttpContext.RequestServices; var logScoped = (ILogScoped)services.GetService(typeof(ILogScoped)); var logTransient = (ILogTransient)services.GetService(typeof(ILogTransient));
It is recommended to use constructor injection instead of getting it using RequestServices.
You can watch our video version of this tutorial with step by step explanation.