Introduction
Understanding the life cycle of Dependency Injection (DI) is very important in ASP.Net Core applications. As we know, Dependency injection (DI) is a technique for achieving loose coupling between objects and their collaborators, or dependencies. Most often, classes will declare their dependencies via their constructor, allowing them to follow the Explicit Dependencies Principle. This approach is known as "constructor injection".
To implement dependency injection, we need to configure a DI container with classes that is participating in DI. DI Container has to decide whether to return a new instance of the service or provide an existing instance. In startup class, we perform this activity on ConfigureServices method.
The lifetime of the service depends on when the dependency is instantiated and how long it lives. And lifetime depends on how we have registered those services.
The below three methods define the lifetime of the services,
- AddTransient: Transient lifetime services are created each time they are requested. This lifetime works best for lightweight, stateless services.
- AddScoped: Scoped lifetime services are created once per request.
- AddSingleton: Singleton lifetime services are created the first time they are requested (or when ConfigureServices is run if you specify an instance there) and then every subsequent request will use the same instance.
Understanding Dependency Injection Lifetime with an Example
Let’s understand DI lifetime with an example in a sample ASP.NET core application.

In my sample project, I added three interfaces called – ItransientService, IScopedService, ISingletonService, which represents one of each of the DI lifetimes. Those interfaces contain a single method called GetOperationID(); which will return a uniqueGuid.
using System;
namespace TransientScopedSingleton {
publicinterfaceITransientService {
Guid GetOperationID();
}
}
using System;
namespace TransientScopedSingleton {
publicinterfaceIScopedService {
Guid GetOperationID();
}
}
using System;
namespace TransientScopedSingleton {
publicinterfaceISingletonService {
Guid GetOperationID();
}
}
Let’s implement those 3 interfaces into a service called OperationService.
using System;
namespace TransientScopedSingleton {
publicclassOperationService: ITransientService,
IScopedService,
ISingletonService {
Guid id;
publicOperationService() {
id = Guid.NewGuid();
}
public Guid GetOperationID() {
return id;
}
}
}
Now, register the OperationService via those three interfaces as shown below in the ConfigureServices method of the startup class.
services.AddTransient<ITransientService, OperationService>();
services.AddScoped<IScopedService, OperationService>();
services.AddSingleton<ISingletonService, OperationService>();
Awesome! Now we are ready to inject those services into controller. For better understanding, we will inject two instances of each service in the constructor of HomeController.
private readonly ILogger<HomeController> _logger;
private readonly ITransientService _transientService1;
private readonly ITransientService _transientService2;
private readonly IScopedService _scopedService1;
private readonly IScopedService _scopedService2;
private readonly ISingletonService _singletonService1;
private readonly ISingletonService _singletonService2;
public HomeController(ILogger<HomeController> logger,
ITransientService transientService1,
ITransientService transientService2,
IScopedService scopedService1,
IScopedService scopedService2,
ISingletonService singletonService1,
ISingletonService singletonService2)
{
_logger = logger;
_transientService1 = transientService1;
_transientService2 = transientService2;
_scopedService1 = scopedService1;
_scopedService2 = scopedService2;
_singletonService1 = singletonService1;
_singletonService2 = singletonService2;
}
Now we will call GetOperationID method of each service instance and assign it to viewbag so that we can see those values in UI.
public IActionResult Index()
{
ViewBag.transient1 = _transientService1.GetOperationID().ToString();
ViewBag.transient2 = _transientService2.GetOperationID().ToString();
ViewBag.scoped1 = _scopedService1.GetOperationID().ToString();
ViewBag.scoped2 = _scopedService2.GetOperationID().ToString();
ViewBag.singleton1 = _singletonService1.GetOperationID().ToString();
ViewBag.singleton2 = _singletonService2.GetOperationID().ToString();
return View();
}


Aditi JaiswalPosted Apr 8, 2024, 7:51 AM
Very clearly explained.
Avinash PhadkePosted Oct 26, 2023, 4:19 PM
That is the most awesome explanation I have ever seen. Thank you a lot Anupam !!!
mohammad hassan mohammadiPosted Sep 4, 2023, 8:49 AM
Thanks ,very good description,with perfect sample
aman deepPosted May 30, 2023, 5:32 AM
Very nicely explained! The simplest and most beautiful explanation.Thanks for this article.
saad khatriPosted May 10, 2023, 6:03 AM
Very nicely explained! Thank you
Niloy NiloyPosted Apr 18, 2023, 7:29 PM
Superb Nice Explanation
Hemanth KumarPosted Mar 2, 2023, 1:54 AM
A good read, thanks for the article. I understood in the first read itself. The simplest and beautiful explanation.
pankaj awaghatePosted Dec 24, 2022, 3:54 AM
Nicely explained & appreciated. Now I am clear with concept. Actually I was struggling for understand the concept practically. Thanks for the help.
Sourav BanerjeePosted Dec 6, 2022, 3:56 PM
Learnt the detail of three using this example. will never forget the help. great find brother.
mimosspprt JonesPosted Aug 10, 2022, 3:47 AM
Thank you!!! great explanation
Kunal BhosalePosted May 2, 2022, 10:08 AM
So which one is better? Does that depends
Francis-Liezl AguiluzPosted Dec 11, 2021, 7:26 AM
Now I understand their differences. Great tut, Great example, Great explanation.
radhe sahPosted Nov 13, 2021, 10:09 AM
Most important part of ,netcore written in great way
anurag rawatPosted Sep 24, 2021, 2:18 PM
Great Article