Ads

.Net Core - Complete Dependency Injection Tour


Hello All,


We will work on dependency injection in this article. We will go through every steps with easy example. At the end of the article you will be able to handle the DI without any issues.


Lets Start...


What is?

Basically Dependency Injection is the design pattern which helps developer to decouple the different pieces of their applications.


Just for Fun in coding : Consider I am going to trip, what I will do? First I will plan for the trip, Then I will take all the necessary things required for my trip and keep all the things in the bag, then will go to trip. While travelling! I will use the items from the bag and keep them back in the bag. In my case Bag is acting as container

 

In general word, It help us to create the application which loosely coupled, means every client no need to create the object instead they can request container(Which is used for DI) to provide the object of the required class.



If No Dependency Injection?


Lets say we have a class called Product we need to use in three pages, Product Detail, Featured Product and Top Product.

To Get the Product Detail in all three pages, we need to create the object of the Product Class in all three pages, which makes code complex

In case disposing, we need to do for all the pages, if we forget to do in any one of the page, then it will be a an issue.

In case any implementation changes, some time we need to do in all the pages, as we are dealing with inline stuffs.


Really Dependency Injection Helps Us:

We use container in Dependency Injection, and register all the dependencies used for the application.

We request container to provide the object of the class requested, instead creating the object. 

In this way container takes whole responsibility of the object creation and disposing.

Dependency Inject is the 5th Principle of solid principle

 

What is IoC?


IoC is also called as Inversion of Control, It is a design pattern or principle suggests that the IoC of various types of controls in Object oriented design to achieve loose coupling between the application classes. 

ASP .NET Core is designed from scratch so it supports dependency injection by default, because of this all the services in ASP .NET Core can be injected into your classes rather than being tightly coupled.

As we know ASP .NET Core has Built in IoC Container.

For legacy, there are a lot of excellent DI Containers that are available

  • StructureMap
  • Spring.NET
  • Autofac
  • Unity
  • Ninject


The Inversion of Controller creates that objects and it sends it over to you in the constructor parameter.

The types of classes that are managed by Inversion of Container is called Services. We have two types of Services.

  1. Framework Services
The service designed by ASP .NET core framework itself
  1. Application Services

The service that we build for our application.


Is There any life time for Services?

Yes, We have....

Basically Dependency Injection Life time is determined by when dependency is instantiated and how long it lives and dependency injection container is completely responsible for this.

In previous version of ASP .NET we had to use third party libraries such as Unity Container, niject etc.. But simple DI Container is built for ASP .NET Core and it does not require a lots of setup.


Can we use third party container?

If you want to us third party container like autofac, you can still use it, but usually the inbuilt dependency Injection Container is good enough for us.

There are three types of Service Lifetimes:

  1. Singleton
  2. Scoped
  3. Transient


1. Singleton:

In this same instance share for the life of the application, until we restart the application.

services.AddSingleTon<Interface, Implementor>();

Example:

If we click on all the views or link on a website, whenever instance is required it will send same object.

We should not forget this, In singleton pattern instance is kept in memory during the whole application lifetime, which will occupy the memory usage. But we have one plus point here i.e. in singleton memory will be allocated only one time, so garbage collector will have less work to do.

The easiest way to think of a single item is to have a static readable in a class. It is singleton even if two users hits our website, the code will still use the same instance.


2. Scoped:

We will have same instance for one scope, example if we create the objects of the class in one function multiple times, then same object will be send to the user.

services.AddScoped<Interface, Implementor>();

Its not best practice to use Scoped for multithreading, because it sends a new instance for each requests.

A good user for Scoped is EntitiFrameWork DbContext class, Here Scoped lifetime within a created scope object.

Final one is Transient....


3. Transient:

Always Sending New Instance Every request is Transient

If we request Product object 10 times, 10 times we will get different objects.

services.AddTransient<Interface, Implementor>();

Lets see with small program.

1. Create New Project "ASP.NET Core Web App(Model View Controller)"



2.  Enter Project Name and Select Project Location Then Click Next



3. Here is the created project



4. Lets Create folder called Interfaces and Add three Interface files in it


5. Here is the Interface class and method declaration

IOperation.cs

namespace Dependency_Injection_Example.Interfaces
{
    public interface IOperation
    {
        Guid OperationId { get; }
    }
}


ITransientExample.cs

namespace Dependency_Injection_Example.Interfaces
{
    public interface ITransientExample : IOperation
    {
        
    }
}


IScopedExample.cs

namespace Dependency_Injection_Example.Interfaces
{
    public interface IScopedExample : IOperation
    {
        
    }
}


ISingleTonExample.cs

namespace Dependency_Injection_Example.Interfaces
{
    public interface ISingleTonExample : : IOperation
    {
        
    }
}


6. Lets create folder called DataAccess and add Operation implementation files in it



7. Here is the detail implementation

Operation.cs

using Dependency_Injection_Example.Interfaces;

namespace Dependency_Injection_Example.DataAccess
{
    public class Operation : ITransientExample, IScopedExample, ISingleTonExample
    {
        Guid _guid;
        public Operation() : this(Guid.NewGuid())
        {

        }

        public Operation(Guid guid)
        {
            _guid = guid;
        }

        public Guid OperationId => _guid;
    }
}


We implement these interfaces using a single class, Operation, that accepts a GUID in its constructor, or uses a new GUID if none is provided:

8. Lets register the interface and its implementation to Dependency Injection. Go to Program.cs and add it


// Add services to the container.
builder.Services.AddSingleton<ISingleTonExample, Operation>();
builder.Services.AddScoped<IScopedExample, Operation>();
builder.Services.AddTransient<ITransientExample, Operation>();
builder.Services.AddTransient<MyOperation2>();


9. Create Class file MyOperation2.cs under Models folder and the below code


using Dependency_Injection_Example.Interfaces;
using Dependency_Injection_Example.Models;
namespace Dependency_Injection_Example.Models
{
    public class MyOperation2
    {
        private readonly ISingleTonExample _singleton;
        private readonly ITransientExample _transient;
        private readonly IScopedExample _scoped;
        public MyOperation2(ISingleTonExample _singleton, ITransientExample _transient, IScopedExample _scoped)
        {
            this._singleton = _singleton;
            this._scoped = _scoped;
            this._transient = _transient;
        }

        public string GetTransientDetail()
        {
            return _transient.OperationId.ToString();
        }

        public string GetScopedDetail()
        {
            return _scoped.OperationId.ToString();
        }

        public string GetSingletonDetail()
        {
            return _singleton.OperationId.ToString();
        }
    }
}


9. Next, Go to HomeController


using Dependency_Injection_Example.Interfaces;
using Dependency_Injection_Example.Models;
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;

namespace Dependency_Injection_Example.Controllers
{
    public class HomeController : Controller
    {
        private readonly ISingleTonExample _singleton;
        private readonly ITransientExample _transient;
        private readonly IScopedExample _scoped;
        public HomeController(ISingleTonExample _singleton, ITransientExample _transient, IScopedExample _scoped)
        {
            this._singleton = _singleton;
            this._scoped = _scoped;
            this._transient = _transient;
        }

        public IActionResult Index()
        {
            //First Request
            ViewBag.Transient = _transient;
            ViewBag.Scoped = _scoped;
            ViewBag.Singleton = _singleton;

            //Second Request
            ViewBag.SecondRequest = _transient;
            ViewBag.Scoped2 = _scoped;
            ViewBag.Singleton2 = _singleton;

            return View();
        }
    }
}


10. Go to View


@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Dependency Injection Life Cycle</h1>
    <hr />
    <h5>First Request</h5>
    <p>Transient : @ViewBag.Transient</p>
    <p>Scoped    : @ViewBag.Scoped</p>
    <p>Singleton : @ViewBag.Singleton</p>

    <h5>Second Request</h5>
    <p>Transient : @ViewBag.Transient2</p>
    <p>Scoped    : @ViewBag.Scoped2</p>
    <p>Singleton : @ViewBag.Singleton2</p>
</div>


11. Lets Run the application




We can notice that Transient has different value, scoped has same value because within the scope and Singleton has same value

Dependency Injection Types:


There are four types we can achieve the Dependency Injection Types.

  1. Constructor Injection
  2. Action Injection
  3. View Injection
  4. Middleware Injection

Constructor Injection:

The Constructor Injection uses a parameter to inject dependencies.
We have requested the object ISingleTonExample and it send the requested object via constructor parameter. Below is the screen




Then we use the object like below




Action Injection:

we can inject an object to the action method Using package called Microsoft.AspNetCore.Mvc.FromServices.


    public IActionResult Privacy([FromServices] MyOperation2 operationp)
    {
        ViewBag.Transient2 = operationp.GetTransientDetail();
        ViewBag.Scoped2 = operationp.GetScopedDetail();
        ViewBag.Singleton2 = operationp.GetSingletonDetail();
        return View();
    }




View Injection:

ASP.NET Core supports dependency injection into views. This can be useful for view-specific services, such as localization or data required only for populating view elements..
As like constructor and Action We can request required object in View also. We use inject keyword to do do this.


@inject Dependency_Injection_Example.Models.MyOperation2 operation

@{
    ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<h1 class="display-4">Dependency Injection</h1>
<hr />
<h5>First Request</h5>
<p>Transient : @operation.GetTransientDetail()</p>
<p>Scoped    : @operation.GetScopedDetail()</p>
<p>Singleton : @operation.GetSingletonDetail()</p>


Output is:




That's it for this article, I hope you enjoyed this. Please let us know in case any concerns or issues via comment section.

Take care see you in next article.
Tags

Post a Comment

0 Comments
* Please Don't Spam Here. All the Comments are Reviewed by Admin.

#buttons=(Accept !) #days=(20)

Our website uses cookies to enhance your experience. Learn More
Accept !