fbpx

ASP.NET Core Dependency Injection and Service Lifetimes

ASP.NET Blog Image

ASP.NET Core supports the Dependency Injection (DI) software design pattern that allows registering services and controlling how these services are instantiated and injected in different components. Also, ASP.NET Core has a built-in IoC container, eliminating the need to use a third-party container to inject the service. Some services will be instantiated for a short time and will be available only in a particular component and request. Some will be instantiated just once and will be available throughout the application.

To inject application services automatically, first register them with the IoC container.

There are two key components in the built-in container:

  1. IServiceCollection – All the services will register here.
  2. IServiceProvider – Implementation supports the constructor injection.
two key components in the built-in container

Figure 01: Key components in the built-in IoC container

Service lifetimes

The built-in IoC container manages the lifetime of the registered service type. It automatically disposes of the service instance according to the specified lifetime.

ASP.NET Core services support three types of lifetimes:

Singleton

A single instance of the registered service class is created and stored in the memory. It is re-used across the application when multiple requests come into the application. Thus, we can use the singleton lifetime for services that are expensive to instantiate.

When using the singleton type in real use cases, you need to consider the following:

  1. The service should not be dependent on other service types.
  2. A singleton instance lasts the entire lifetime of the application until it is terminated. Therefore, the instance should be disposed properly. If not, it can cause a performance issues in the application.

Figure 02: Singleton instances are created the first time they are requested

How to register the singleton service .NET Core during startup.

public void ConfigureServices(IServiceCollection services)

{
      services.AddSingleton<IProductService, ProductService>();

}

Scoped

Think of a scoped lifetime as a service instance that is created per web request. The request will be considered as scope. This lifetime works best for lightweight, stateless services.

A common usage of this approach is to declare the DbContext class of Entity Framework Core. The lifetime of a DbContext begins when the instance is created and ends when the instance is disposed.

Figure 3: Scoped

Figure 03: A scoped lifetime denotes that services are created once per client web request.

How to register the scoped service .NET Core during startup.

public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IProductService, ProductService>();
}

Transient

Figure 4: Transient

Figure 04: Transient lifetime services are created each time they are requested from the service container

Each time a service is requested, a new instance will be created. This is the most common and always the safest option if you are worried about multithreading.

If we inject the same service into a Controller and a View in an MVC application, two different instances will be created in the controller and the view.

How to register the transient service .NET Core during startup.

public void ConfigureServices(IServiceCollection services)

{        services.AddTransient<IProductService, ProductService>();

}

“In terms of the lifetime of the instance, the Singleton object gets the highest life per instantiation, followed by a Scoped service object and the least by a Transient object.”

Written by

Lakshika Sivapragasam

Senior Software Engineer, Fortude