Today, I am going to explain in detail about dependency injection in C#. This article is for those developers who don't know anything about Dependency Injection (DI). Just go through all the examples below along with code comments to get a better understanding of DI.
Before we start DI, let's understand what tightly coupled is in C#. If you are familiar with tightly coupled, then skip this section.
Tightly coupled in C#
Tight coupling is when a group of classes are highly dependent on one another. See the below example which is tightly coupled.
- public class SavingAccount
- {
- public void PrintData()
- {
- Console.WriteLine("Saving account data.");
- }
- }
- public class CurrentAccount
- {
- public void PrintData()
- {
- Console.WriteLine("Current account data.");
- }
- }
- //This account class is tightly couple as every time,
- //we need to create the instance of both SavingAccount
- //and CurrentAccount class to call the PrintData() method of each.
- public class Account
- {
- //Here I need to craete the SavingAccount object
- //to call the SavingAccount PrintData()
- SavingAccount savingAccount = new SavingAccount();
- //Here I need to craete the CurrentAccount object
- //to call the SavingAccount PrintData()
- CurrentAccount currentAccount = new CurrentAccount();
- public void PrintAccounts()
- {
- savingAccount.PrintData();
- currentAccount.PrintData();
- }
- }
- public class Program
- {
- static void Main(string[] args)
- {
- Account account = new Account();
- account.PrintAccounts();
- Console.ReadLine();
- }
- }
The account class is tightly coupled as every time, we need to create the instance of both SavingAccount and CurrentAccount class to call the PrintData() method of each. So it is highly dependent on either SavingAccount or CurrentAccount class.
Now the question is, how to avoid this tightly coupled state? The answer is by using Dependency injection. DI is achieved using interfaces.
What is Dependency Injection in C#?
Dependency Injection (DI) is a software pattern. DI is a technique whereby one object supplies the dependencies of another object. With the help of DI, we can write loosely coupled code. A loosely-coupled code is a code where all your classes can work independently without relying on each other. There are four types of DI in C#
- Constructor Injection
- Setter or property Injection
- Method Injection
- Service Locator Injection
I am not discussing the "Service Locator Injection". Let us understand constructor, setter or property, and method injection with an example.
DI using Constructor Injection
Constructor injection is nothing but the process of injecting dependent class object through the constructor. What is meant by this?
In the above example, the account class has a dependency on SavingAccount & CurrentAccount classes. So constructor injection means, injecting SavingAccount & CurrentAccount class objects in Account class constructor using interface. Let us see how we can do this.
- //Created IAccount interface to make code loosely coupled.
- public interface IAccount
- {
- void PrintData();
- }
- //Implemented the IAccount interface in SavingAccount class
- public class SavingAccount : IAccount
- {
- public void PrintData()
- {
- Console.WriteLine("Saving account data.");
- }
- }
- //Implemented the IAccount interface in CurrentAccount class
- public class CurrentAccount : IAccount
- {
- public void PrintData()
- {
- Console.WriteLine("Current account data.");
- }
- }
- //Account class is not depended on any other classes.
- //So now it is loosely coupled.
- public class Account
- {
- private IAccount account;
- //Passing IAccount interface as parameter to Account constructor
- public Account(IAccount account)
- {
- this.account = account;
- }
- public void PrintAccounts()
- {
- account.PrintData();
- }
- }
- class Program
- {
- static void Main()
- {
- //If you want to calls the SavingAccount class PrintAccounts() method,
- //just created the object of SavingAccount() and
- //pass as parameter to Account constructor.
- IAccount savingAccount = new SavingAccount();
- Account account = new Account(savingAccount);
- account.PrintAccounts();
- //If you want to calls the CurrentAccount class PrintAccounts() method,
- //just created the object of CurrentAccount () and
- //pass as parameter to Account constructor.
- IAccount currentAccount = new CurrentAccount();
- account = new Account(currentAccount);
- account.PrintAccounts();
- Console.ReadLine();
- }
- }
Output

Here, I have created a separate "IAccount" interface to make the code loosely coupled. So, we have to use "IAccount" interface to inject SavingAccount & CurrentAccount class objects in Account class constructor. That's why I have Implemented the IAccount interface in SavingAccount and CurrentAccount. If you see the code the "Account" class, there is no class object created. Hence, Account class is not dependent on any other classes and now it is loosely coupled.
I have passed the "IAccount" interface as a parameter to "Account" class constructor to implement constructor DI.
In the main method, If you want to calls the SavingAccount class PrintAccounts() method, just create the object of SavingAccount() and pass as a parameter to Account constructor.
Similarly, In the main method, If you want to call the CurrentAccount class PrintAccounts() method, just create the object of CurrentAccount () and pass as a parameter to Account constructor.

Hence, now there are not classes dependent on each other.
DI using Setter or Property Injection
Setter or property injection is injecting dependent class object through the property. So setter or property injection means, injecting SavingAccount & CurrentAccount class objects in Account class using property. Here the property type will be an interface. Let's see, how we can do this.
- //Created IAccount interface to make code loosely coupled.
- public interface IAccount
- {
- void PrintData();
- }
- //Implemented the IAccount interface in SavingAccount class
- public class SavingAccount : IAccount
- {
- public void PrintData()
- {
- Console.WriteLine("Saving account data.");
- }
- }
- //Implemented the IAccount interface in SavingAccount class
- public class CurrentAccount : IAccount
- {
- public void PrintData()
- {
- Console.WriteLine("Current account data.");
- }
- }
- //Account class is not depended on any other classes.
- //So now it is loosely coupled.
- public class Account
- {
- //Here my account property is of type IAccount interface
- public IAccount account { get; set; }
- public void PrintAccounts()
- {
- account.PrintData();
- }
- }
- class Program
- {
- static void Main()
- {
- //If you want to calls the SavingAccount class PrintAccounts() method,
- //just created the object of SavingAccount() and
- //assign it to IAccount interface property (i.e. account)
- Account savingAccount = new Account();
- savingAccount.account = new SavingAccount();
- savingAccount.PrintAccounts();
- //If you want to calls the CurrentAccount class PrintAccounts() method,
- //just created the object of CurrentAccount () and
- //assign it to IAccount interface property (i.e. account)
- Account currentAccount = new Account();
- currentAccount.account = new CurrentAccount();
- currentAccount.PrintAccounts();
- Console.ReadLine();
- }
- }
Output
DI using Method Injection
Method Injection is injecting dependent class object through a class method. What is mean by this?
In the above example, Account class has a dependency on SavingAccount and CurrentAccount classes. So the method Injection means, injecting SavingAccount & CurrentAccount class objects directly into the Account class method user interface. Let's see how we can do this.
- //Created IAccount interface to make code loosely coupled.
- public interface IAccount
- {
- void PrintData();
- }
- //Implemented the IAccount interface in SavingAccount class
- public class SavingAccount : IAccount
- {
- public void PrintData()
- {
- Console.WriteLine("Saving account data.");
- }
- }
- //Implemented the IAccount interface in SavingAccount class
- public class CurrentAccount : IAccount
- {
- public void PrintData()
- {
- Console.WriteLine("Current account data.");
- }
- }
- //Account class is not depended on any other classes.
- //So now it is loosely coupled.
- public class Account
- {
- //Passing "IAccount" as parameter to PrintAccounts() method
- public void PrintAccounts(IAccount account)
- {
- account.PrintData();
- }
- }
- class Program
- {
- static void Main()
- {
- //If you want to calls the SavingAccount class PrintAccounts() method,
- //just created the object of SavingAccount() and directly pass as parameter
- //to Account class method (i.e PrintAccounts(new SavingAccount())).
- Account savingAccount = new Account();
- savingAccount.PrintAccounts(new SavingAccount());
- //If you want to calls the CurrentAccount class PrintAccounts() method,
- //just created the object of CurrentAccount() and directly pass as parameter
- //to Account class method (i.e PrintAccounts(new SavingAccount())).
- Account currentAccount = new Account();
- currentAccount.PrintAccounts(new CurrentAccount());
- Console.ReadLine();
- }
- }
Output
I hope now you are very familiar with DI and types of DI.
Happy coding.......

Karthikeyan PPosted Jul 15, 2021, 8:23 PM
Thank you so much for this article.
Abhay SharmaPosted Sep 19, 2020, 1:47 AM
Really ,great explanation. Thanks Mahesh.............:)
Ahmed Abd ElmoniemPosted Aug 25, 2020, 3:23 AM
Is there any way to use "DI using Setter or Property Injection" with services on .net core web projects?
satya kumarPosted Feb 12, 2020, 12:59 PM
This is very helpful and crystal clear to understand.
Chris CatignaniPosted Jan 22, 2020, 11:15 PM
Well done!
Humayun Kabir MamunPosted Nov 5, 2018, 8:41 PM
Thanks for this helpful article
Hiten PandyaPosted Nov 4, 2018, 10:47 PM
Superb article on DI. It really helps me to clear concept of DI. Thank you so much for sharing.
Rushi MehtaPosted Nov 4, 2018, 10:07 PM
Nice Article written