# Life cycle of Dependency Injection

Understanding the lifecycle of services created using Dependency Injection is very important before using them. Creating services without understanding the difference between Transient, Singleton, and Scoped can cause the system to not work as expected. When a service requests another service through DI, it is important to know whether it received a new instance or an existing instance. Therefore, it is very important to be aware of the correct life cycle or life time while registering a service.

## Service lifecycle management&#x20;

Whenever we request a service, the DI Container decides whether to create a new instance or reuse the previously created instance. The service life cycle depends on when the instance is instantiated and how long it lives. We define the lifecycle when we register the service.

We learned how to use DI in the previous lesson. There are 3 lifecycle levels, this way we can decide how each service has a lifecycle.

**Transient**: A new instance is always created, every time it is requested.&#x20;

**Scoped**: Create a new instance for all scopes (Each request is a scope). In scope, the service is reused&#x20;

**Singleton**: Service is created only once.

## Project example&#x20;

Create a new Service Interface Create a new service named SomeService in the Services folder. Add 3 new interfaces. Each interface corresponds to a lifecycle in ASP.NET Core. The interface is simple, they contain each GetID method that returns a Guid.

```csharp
public interface ITransientService 
{ 
    Guid GetID();
}
 
public interface IScopedService 
{ 
   Guid GetID();
}

public interface ISingletonService 
{ 
   Guid GetID();
}
```

Create a Service Now we will create a single service that implements all three interfaces:

```csharp
public class SomeService : ITransientService, IScopedService, ISingletonService 
{ 
    Guid id;
     
    public SomeService() 
    { 
        id = Guid.NewGuid(); 
    }
    public Guid GetID()
    {
        return id;
    }
}
```

The service generates a unique ID and it will be initialized and return the id in the GetID method. Now let's see the details

### Transient&#x20;

The Transient Service always creates a new one each time the service is requested

#### Sign up for Transient Service&#x20;

Now inside the ConfigureServices method of Startup will register SomeService through the ITransientService interface.

```csharp
services.AddTransient<ITransientService, SomeService>();
```

#### Inject into Controller&#x20;

Open the HomeController and inject 2 instances of SomeService as shown below:

```csharp
public class HomeController : Controller
{
    ITransientService _transientService1;
    ITransientService _transientService2;

    public HomeController(ITransientService transientService1,
                          ITransientService transientService2)
    {
        _transientService1 = transientService1;
        _transientService2 = transientService2;
    }

    public IActionResult Index()
    {

        ViewBag.message1 ="First Instance " + _transientService1.GetID().ToString();
        ViewBag.message2 ="Second Instance "+ _transientService2.GetID().ToString();

        return View();
    }
}
```

First, we inject two service instances through the ITransientService interface in the HomeController constructor.

```csharp
public HomeController(ITransientService transientService1,ITransientService transientService2)
```

Next, we call the GetID method in each instance and assign it to the view using ViewBag.

```csharp
ViewBag.message1 ="First Instance " + _transientService1.GetID().ToString();
ViewBag.message2 ="Second Instance "+ _transientService2.GetID().ToString();
```

#### View

```csharp
<h3>Transient Service</h3>
@ViewBag.message1
</br>
@ViewBag.message2
```

Run the application and you will see 2 different Guids displayed on the screen. The proof is that we got 2 instances of the Transient service.

<figure><img src="https://1722711354-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwNXdoUkfmcozr29fRrfb%2Fuploads%2FZzsO6iVOLmHaOm8k3gE1%2Fimage.png?alt=media&#x26;token=f2d05983-5156-400b-a906-7d137a6cc366" alt=""><figcaption></figcaption></figure>

### Scoped&#x20;

Services with scoped lifecycle are created only once per request (scope). A new instance is created for each request and the instance is reused in the request.

#### Sign up for Scoped Service

In the ConfigureServices method register SomeService using the AddScoped method using the IScopedService interface.

```csharp
services.AddScoped<IScopedService, SomeService>();
```

#### Inject scoped service into Controller&#x20;

Next inject this service into the Controller. We already have a transient service injected into the controller. Now nothing has changed but added a new one:

```csharp
public class HomeController : Controller
{
    ITransientService _transientService1;
    ITransientService _transientService2;

    IScopedService _scopedService1;
    IScopedService _scopedService2;

    public HomeController(ITransientService transientService1,
                          ITransientService transientService2, 
                          IScopedService scopedService1,
                          IScopedService scopedService2)
    {
        _transientService1 = transientService1;
        _transientService2 = transientService2;

        _scopedService1 = scopedService1;
        _scopedService2 = scopedService2;
    }

    public IActionResult Index()
    {
        ViewBag.message1 ="First Instance " + _transientService1.GetID().ToString();
        ViewBag.message2 ="Second Instance "+ _transientService2.GetID().ToString();

        ViewBag.message3 = "First Instance " + _scopedService1.GetID().ToString();
        ViewBag.message4 = "Second Instance " + _scopedService2.GetID().ToString();

        return View();
     }
}
```

Add to action method 2 variables message3 and message4 for scoped service.

#### View&#x20;

In view add 3 lines

```csharp
<h3>Scoped Service</h3>
@ViewBag.message3
</br>
@ViewBag.message4
```

Run the application. The instance is created only once per request, that's why we create 2 identical IDs. Now refresh the browser. The ID has changed because a new instance is created for each request.

<figure><img src="https://1722711354-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwNXdoUkfmcozr29fRrfb%2Fuploads%2F9EFxl792Mw7dsEgdwNAf%2Fimage.png?alt=media&#x26;token=4825478b-5fbc-4f9a-a0d6-45d39325cd9e" alt=""><figcaption></figcaption></figure>

### Singleton&#x20;

A single instance of the service is created when it is first requested. Then each subsequent request will only use that same instance. The new request does not create a new instance, it is reused.

#### Register Singleton Service&#x20;

Singleton service is registered using the AddSingleton

```csharp
services.AddSingleton<ISomeServiceService, SomeService>();
```

#### Inject Singleton service into Controller

```csharp
public class HomeController : Controller
{
    ITransientService _transientService1;
    ITransientService _transientService2;

    IScopedService _scopedService1;
    IScopedService _scopedService2;

    ISingletonService _singletonService1;
    ISingletonService _singletonService2;

    public HomeController(ITransientService transientService1,
                      ITransientService transientService2, 
                      IScopedService scopedService1,
                      IScopedService scopedService2,
                      ISingletonService singletonService1,
                      ISingletonService singletonService2)
    {

        _transientService1 = transientService1;
        _transientService2 = transientService2;

        _scopedService1 = scopedService1;
        _scopedService2 = scopedService2;

        _singletonService1 = singletonService1;
        _singletonService2 = singletonService2;
     }

     public IActionResult Index()
     {
         ViewBag.message1 ="First Instance " + _transientService1.GetID().ToString();
         ViewBag.message2 ="Second Instance "+ _transientService2.GetID().ToString();

         ViewBag.message3 = "First Instance " + _scopedService1.GetID().ToString();
         ViewBag.message4 = "Second Instance " + _scopedService2.GetID().ToString();

         ViewBag.message5 = "First Instance " + _singletonService1.GetID().ToString();
         ViewBag.message6 = "Second Instance " + _singletonService2.GetID().ToString();

         return View();
     }
}
```

First we inject 6 instances of SomeService. Two instances for each interface.

#### View

```
@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

<h3>Transient Service</h3>
@ViewBag.message1
</br>
@ViewBag.message2

<h3>Scoped Service</h3>
@ViewBag.message3
</br>
@ViewBag.message4

<h3>Singleton Service</h3>
@ViewBag.message5
</br>
@ViewBag.message6
```

Run the application and you will see that the IDs generated from the Singleton service are always the same and will not change even if you refresh the application. You can see in the picture below

<figure><img src="https://1722711354-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwNXdoUkfmcozr29fRrfb%2Fuploads%2F7O872KfWKxaBVMlWGB0d%2Fimage.png?alt=media&#x26;token=0da30cb6-8b5e-42c1-9b78-fc69a39fb3f5" alt=""><figcaption></figcaption></figure>

## So which one should be used?&#x20;

Transient service is the safest way to create, since you are always creating a new instance. But because of that it will create each time you request so will use more memory and resources. This may adversely affect performance if too many instances are created.

Using Transient Service is suitable when you want to use for lightweight and small and stateless services.

Scoped service is better when you want to maintain state within a request.

Singleton is created only once, it is not destroyed until application shutdown. Any memory usage with these services builds up over time and it fills up. But also helps us save memory if handled well because they are created only once and used everywhere.

Use Singleton when you need to maintain system-wide state. Configuration, application parameters, service logging, data caching... are common examples of Singleton usage.

## Inject service with different lifecycle into another service&#x20;

Be careful, when injecting services into other services with different lifecycles. Let's see an example Singleton Service that depends on another service registered with a lifecycle of Transient.

When the request first arrives, an instance of the Singleton is created.

When the second request arrives, this instance of the Singleton is reused. And this singleton already contains an instance of the transient service. So it is not recreated. This invisibly converted a transient service into a singleton service.

Services with a lower lifecycle injected into a service with a higher lifecycle will change a lower lifecycle service to a higher lifecycle service. This will make debugging harder and it should be avoided. From low to high are Transient, Scoped and Singleton.

So remember the rule:

* Never inject Scoped & Transient service into Singleton service&#x20;
* Never inject Transient Service into Scope Service
