Introduction
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:
- DI details
- DI code example
- Create ASP.NET Core MVC web project
- Code implementation
- Conclusion
Dependency Injection
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.
public class MobilePhone
{
public void CallFunction()
{
Console.WriteLine("It Ensure Mobile Call Function");
}
public void IneternetBrowse()
{
Console.WriteLine("It Ensure Internet Browse Function");
}
}
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
- Constructor Injection
- Setter Injection
- 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.
public interface IMobilePhone
{
void CallFunction();
void IneternetBrowse();
}
public class MobilePhone : IMobilePhone
{
public void CallFunction()
{
Console.WriteLine("It Ensure Mobile Call Function");
}
public void IneternetBrowse()
{
Console.WriteLine("It Ensure Internet Browse Function");
}
}
public class Human
{
IMobilePhone _mobilePhone;
public Human(IMobilePhone mobilePhone)
{
_mobilePhone = mobilePhone;
}
public void BasciNeed()
{
_mobilePhone.CallFunction();
_mobilePhone.IneternetBrowse();
}
}
What SOLID 5th Principles Says
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
Code Implementation
public interface ICommonData
{
DateTime GetCurrentDateTime();
string GetMachineName();
}
public class CommonData : ICommonData
{
public DateTime GetCurrentDateTime()
{
return DateTime.Now;
}
public string GetMachineName()
{
return Environment.MachineName.ToString();
}
}
Controller
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:
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:
The Benefits of DI
- Unit testing is much easier and simpler with different mock implementation
- Loosely coupled not tightly coupled which is very important for any application
- Followed SOLID principal as well
- Configurable
- Ensure code is clean and more readable
- 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