How to use Dependency Injection in ASP.NET Core

How to use Dependency Injection in ASP.NET Core

Introduction

In this article, we’ll learn Service Lifetimes for Dependency Injection in .NET Core. and also understand how DI works in .NET Core. Please, read our previous article before proceeding to this article where we learn Static Files Middleware in ASP.NET Core.

What is Dependency Injection?

The Dependency Injection (DI) is a model that can help developers decouple the various pieces of their applications. At the point When a system is designed to utilize DI, with many classes requesting their dependencies through their constructor (or properties), it’s helpful to have a class committed to making these classes with their related dependencies. all classes are referred to as containers, or more specifically, Inversion of Control (IoC) containers or Dependency Injection (DI) containers. A container is basically a factory that’s responsible for providing instances of types that are requested from it.

Microsoft .NET Core framework

Microsoft .NET Core incorporates a straightforward built-in container (represented by the IServiceProvider interface) that supports constructor injection. The NameSpace under which it is incorporated is Microsoft.Extensions.DependencyInjection.

Dependency Lifetimes

At the registration time, class dependencies require a lifetime definition. The service lifetime defines the conditions under which another new service instance will be created.

The following are the lifetimes characterized by the .NET Core DI framework.

Transient

Created every time they are requested.

Scoped

Created once per scope; i.e., web request.or any unit of work

Singleton

Every time it’s created only for the first request. If a specific occurrence is specified at registration time, this instance will be provided to all consumers of the registration type.

Let’s understand the Dependency Injection example using a simple snippet of code for console application below.

public interface IService  
   {  
       void Info();  
   }  
  
   public interface ISingleton : IService { }  
   public interface IScoped : IService { }  
   public interface ITransient : IService { }  
  
   public abstract class Operation : ISingleton, IScoped, ITransient  
   {  
       private Guid _operationId;  
       private string _lifeTime;  
  
       public Operation(string lifeTime)  
       {  
           _operationId = Guid.NewGuid();  
           _lifeTime = lifeTime;  
  
           Console.WriteLine($"{_lifeTime} Service Created.");  
       }  
  
       public void Info()  
       {  
           Console.WriteLine($"{_lifeTime}: {_operationId}");  
       }  
   }  
  
   public class SingletonOperation : Operation  
   {  
       public SingletonOperation() : base("Singleton") { }  
   }  
   public class ScopedOperation : Operation  
   {  
       public ScopedOperation() : base("Scoped") { }  
   }  
   public class TransientOperation : Operation  
   {  
       public TransientOperation() : base("Transient") { }  
   }  
  
   class Program  
   {  
       static void Main(string[] args)  
       {  
           var serviceProvider = new ServiceCollection()  
               .AddTransient<ITransient, TransientOperation>()  
               .AddScoped<IScoped, ScopedOperation>()  
               .AddSingleton<ISingleton, SingletonOperation>()  
               .BuildServiceProvider();  
  
           Console.WriteLine("========== Request 1 ============");  
           serviceProvider.GetService<ITransient>().Info();  
           serviceProvider.GetService<IScoped>().Info();  
           serviceProvider.GetService<ISingleton>().Info();  
           Console.WriteLine("========== ========= ============");  
  
           Console.WriteLine("========== Request 2 ============");  
           serviceProvider.GetService<ITransient>().Info();  
           serviceProvider.GetService<IScoped>().Info();  
           serviceProvider.GetService<ISingleton>().Info();  
           Console.WriteLine("========== ========= ============");  
  
           using (var scope = serviceProvider.CreateScope())  
           {  
               Console.WriteLine("========== Request 3 ============");  
               scope.ServiceProvider.GetService<IScoped>().Info();  
               scope.ServiceProvider.GetService<ITransient>().Info();  
               scope.ServiceProvider.GetService<ISingleton>().Info();  
               Console.WriteLine("========== ========= ============");  
  
               Console.WriteLine("========== Request 4 ============");  
               scope.ServiceProvider.GetService<IScoped>().Info();  
               scope.ServiceProvider.GetService<ISingleton>().Info();  
               Console.WriteLine("========== ========= ============");  
           }  
  
           using (var scope = serviceProvider.CreateScope())  
           {  
               Console.WriteLine("========== Request 5 ============");  
               scope.ServiceProvider.GetService<IScoped>().Info();  
               scope.ServiceProvider.GetService<ISingleton>().Info();  
               Console.WriteLine("========== ========= ============");  
           }  
  
           Console.WriteLine("========== Request 6 ============");  
           serviceProvider.GetService<IScoped>().Info();  
           Console.WriteLine("========== ========= ============");  
  
           Console.ReadKey();  
       }  
  
  
   }  

Below Sample Output

========== Request 1 ============  
Transient Service Created.  
Transient: 6958dca3-05a7-4322-82b6-dec6fcacefeb  
Scoped Service Created.  
Scoped: c1098528-5855-46f7-a284-ba2a1dff0769  
Singleton Service Created.  
Singleton: 5ca7706b-5181-49ff-be09-5493f0decc0d  
========== ========= ============

Transient Service Created.

========== Request 2 ============
Transient: c7710765-0b09-43bd-86f4-0ef022ed5220  
Scoped: c1098528-5855-46f7-a284-ba2a1dff0769  
Singleton: 5ca7706b-5181-49ff-be09-5493f0decc0d  
========== ========= ============

Scoped Service Created.

========== Request 3 ============    
Scoped: 6d5d7842-468f-4040-907c-6b2ab907df61  
Transient Service Created.  
Transient: 1ec15435-dda2-4fe0-8e29-c154c0352c95  
Singleton: 5ca7706b-5181-49ff-be09-5493f0decc0d
========== Request 4 ============  
Scoped: 6d5d7842-468f-4040-907c-6b2ab907df61  
Singleton: 5ca7706b-5181-49ff-be09-5493f0decc0d  
========== ========= ============  

========== Request 5 ============  
Scoped Service Created.  
Scoped: 2ad1a715-09b0-4aac-9b84-2df376cc2223  
Singleton: 5ca7706b-5181-49ff-be09-5493f0decc0d  
========== ========= ============  

========== Request 6 ============  
Scoped: c1098528-5855-46f7-a284-ba2a1dff0769

Output Analysis

Transient – (Request 1,2,3)

In the above output, we can see that another new instance transient service is created whatever the service is requested.

Singleton – (Request 1,2,3,4,5)

In the above output, we can see that a singleton service is only created when it is required for the first time run. In the next subsequent requests, the same occurrences are provided.

Scope – (Request 1,2,3,4,5,6)

In the sample program, we have 3 scopes,
For the Main function
For Request 3 & 4
For Request 5

In the above output, we can see that a scoped service is only created when it is required the first run through in a specific scope. In short, it works like a Singleton service inside a given scope.

Thank you for reading this article, I hope you will understand the Dependency Injection in ASP.NET Core. We’ll get into more details about this when we’ll learn Controllers in ASP.NET Core MVC in the next article.

Leave a Reply

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