Click here to Skip to main content
15,868,016 members
Articles / Programming Languages / C#

Dependency Injection(DI) in ASP.NET Core

Rate me:
Please Sign up or sign in to vote.
1.86/5 (12 votes)
13 Oct 2019CPOL4 min read 11.1K   317   11   7
This article will walk you through the basic understanding of DI, why DI, code example and creation of ASP.NET Core MVC web application by using .NET Core built-in DI.

Introduction

apple fruit with plastic syringes

Photo by Thanh Tran on Unsplash

Dependency Injection (DI) is an Object-Oriented Programming(OOP) design pattern that allows us to confirm loosely coupled implementation in the application.

Suppose we have two pretty simple classes namely as Human class and MobilePhone class. MobilePhone class has just CallFunction and InternetBrowse functionality. Human class uses MobilePhone class functionality by creating new objects of class MobilePhone inside Human class.

As a result, the Human class completely depends on MobilePhone class. Dependency Injection helps us to remove the dependency on the other class by supplying the dependencies of other class objects.

Basically, DI is a technique or process that one object supplies the dependencies of another object.

Prerequisites

  • Good knowledge of C# language
  • ASP.NET Core MVC web application
  • .NET CLI
  • Useful to have good knowledge of the SOLID principal

Background

Now move to this demonstration and let me create an ASP.NET Core MVC web application. The article objective will cover as follows:

  1. DI details
  2. DI code example
  3. Create ASP.NET Core MVC web project
  4. Code implementation
  5. Conclusion

Dependency Injection

Image 2

Tight Coupling

If a class directly or concretely has the dependency on another class, then it said to be tightly coupled. That means changing one object required to change another object as well. It's okay in a small application but in an enterprise-level application, it is too difficult to make the changes.

Loose Coupling

It ensures two objects are independent and the creation of objects outside the class without being dependent on other classes.

As I mentioned in the introduction section, Human class, and MobilePhone class dependency relationship and here is a code example without using DI. Human class is completely dependent on the MobilePhone class. It's a dependency. We can resolve this dependency by using Dependency Injection. Later, I will show the use of DI in the codebase by creating the ASP.NET Core MVC web project.

C#
public class MobilePhone
    {
        public void CallFunction()
        {
            Console.WriteLine("It Ensure Mobile Call Function");
        }
 
        public void IneternetBrowse()
        {
            Console.WriteLine("It Ensure Internet Browse Function");
        }
    }
C#
public class Human
    {
        MobilePhone _MobilePhone = new MobilePhone();
        public void BasciNeed()
        {
            _MobilePhone.CallFunction();
            _MobilePhone.IneternetBrowse();
        }
    }

The problem is when in the future the MobilePhone class has changed, then you have to change Human as well. For example, if MobilePhone class adds a new parameter base constructor, then the Human class absorbs it by changing the current implementation. To solve this complexity, we have to use DI.

DI container helps us by creating an object outside the class and providing it at the right time when we required it so that we don't think about object creation. As a result, our code becomes clean, maintainable and loosely coupled.

Classification of DI

  1. Constructor Injection
  2. Setter Injection
  3. Method Injection

Now I will illustrate Constructor Injection with details examples.
Let's see the above example using Constructor Injection. DI is served as a service. When we need MobilePhone class object, we just knock the DI container, please give us the expected object. We don't have any worry regarding object creation and changed the existing code as well. DI container will make sure of it. It's a great relief.

C#
public interface IMobilePhone
    {       
        void CallFunction();
        void IneternetBrowse();
    }
C#
public class MobilePhone : IMobilePhone
    {
        public void CallFunction()
        {
            Console.WriteLine("It Ensure Mobile Call Function");
        }
 
        public void IneternetBrowse()
        {
            Console.WriteLine("It Ensure Internet Browse Function");
        }
    }
C#
public class Human
    {
        IMobilePhone _mobilePhone;
        public Human(IMobilePhone mobilePhone)
        {
            _mobilePhone = mobilePhone;
        }
        public void BasciNeed()
        {
            _mobilePhone.CallFunction();
            _mobilePhone.IneternetBrowse();
        }
    }

What SOLID 5th Principles Says

  • One should depend upon abstractions, not concretions.
  • High-level modules should not depend on low-level modules.
  • Both should depend on abstractions.
  • Abstractions should not depend on details. Details should depend on abstractions.
  • So high-level and low-level modules and details depend on abstractions:
    Abstractions: High-level + Low-level modules + Details
    • High-level modules: describe those operations in our application that have more abstract nature and contain more complex logic. These modules orchestrate low-level modules in our application.
    • Low-level modules: contain more specific individual components focusing on details and smaller parts of the application. These modules are used inside the high-level modules in our application.

Create ASP.NET Core MVC Web Project

Let's first create an ASP.NET Core MVC web application using .NET Core CLI.

$ dotnet new sln -n DotNetCoreDI
$ dotnet new mvc -n DotNetCoreDI
$ dotnet sln DotNetCoreDI.sln add DotNetCoreDI/DotNetCoreDI.csproj

Image 3

Code Implementation

C#
public interface ICommonData
    {
        DateTime GetCurrentDateTime();
        string GetMachineName();
    }
C#
public class CommonData : ICommonData
    {
        public DateTime GetCurrentDateTime()
        {
            return DateTime.Now;
        }
        public string GetMachineName()
        {
            return Environment.MachineName.ToString();
        }
    }

Controller

C#
private readonly ICommonData _commonData;
public HomeController(ICommonData commonData)
{
    _commonData = commonData;
}

public IActionResult Index()
{
    var serverTime = _commonData.GetCurrentDateTime();
    ViewData["CurrentTime"] = serverTime;

    if (serverTime.Hour < 12)
    {
        ViewData["Message"] = "It's morning here - Good Morning!";
        
    }
    else if (serverTime.Hour < 17)
    {
        ViewData["Message"] = "It's afternoon here - Good Afternoon!";
    }
    else
    {
        ViewData["Message"] = "It's evening here - Good Evening!";
    }

    ViewData["MachineName"] = _commonData.GetMachineName();

    return View();
}

Build and Run

$ dotnet build
$ dotnet run

If you run the project without configuring DI in Startup.cs, then the program will throw the following exception:

Image 4

DI Configuration

ASP.NET Core supports the dependency injection (DI) software design pattern. In the console application, you have to install Microsoft Dependency Injection Extensions over the NuGet package manager.

PM> Install-Package Microsoft.Extensions.DependencyInjection -Version 3.0.0
services.AddTransient<ICommonData, CommonData>();

Now, if we run the project, then we can see the following output:

Image 5

The Benefits of DI

  1. Unit testing is much easier and simpler with different mock implementation
  2. Loosely coupled not tightly coupled which is very important for any application
  3. Followed SOLID principal as well
  4. Configurable
  5. Ensure code is clean and more readable
  6. Reduced module complexity, increased system maintainability and module reusability

Conclusion

In this article, I just tried to explain the basics of Dependency Injection, use of DI and code example with ASP.NET Core MVC web application.

We can use another class object without using dependency injection but it has few drawbacks and complexity. To overcome this drawback, we need to use dependency injection. The SOLID principle says we should handle dependencies outside the dependent class. The best part of DI is ensured loosely coupling which ensures clean code and good maintainable of the codebase as well.

Until next time, happy learning!

Cheers!

History

  • 14th October, 2019: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Program Manager
Bangladesh Bangladesh
PM, CSM®, CSD®

Comments and Discussions

 
QuestionThe explanation should be much more intuitive. Pin
BDisp17-Oct-19 4:47
BDisp17-Oct-19 4:47 
AnswerRe: The explanation should be much more intuitive. Pin
RM Shahidul Islam Shahed20-Oct-19 20:47
RM Shahidul Islam Shahed20-Oct-19 20:47 
QuestionThe DI Container? Pin
George Swan15-Oct-19 23:16
mveGeorge Swan15-Oct-19 23:16 
AnswerRe: The DI Container? Pin
RM Shahidul Islam Shahed20-Oct-19 21:03
RM Shahidul Islam Shahed20-Oct-19 21:03 
GeneralMy vote of 1 Pin
Emil Steen15-Oct-19 0:39
Emil Steen15-Oct-19 0:39 
GeneralRe: My vote of 1 Pin
RM Shahidul Islam Shahed20-Oct-19 21:11
RM Shahidul Islam Shahed20-Oct-19 21:11 
GeneralRe: My vote of 1 Pin
Emil Steen21-Oct-19 2:07
Emil Steen21-Oct-19 2:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.