Understanding Dependency Injection Using Constructor, Property, And Method In C#

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.

Let's start,

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.

  1. public class SavingAccount  
  2. {  
  3.     public void PrintData()  
  4.     {  
  5.         Console.WriteLine("Saving account data.");  
  6.     }  
  7. }  
  8.   
  9. public class CurrentAccount  
  10. {  
  11.     public void PrintData()  
  12.     {  
  13.         Console.WriteLine("Current account data.");  
  14.     }  
  15. }  
  16.   
  17. //This account class is tightly couple as every time,   
  18. //we need to create the instance of both SavingAccount   
  19. //and CurrentAccount class to call the PrintData() method of each.  
  20. public class Account  
  21. {  
  22.     //Here I need to craete the SavingAccount object   
  23.     //to call the SavingAccount PrintData()  
  24.     SavingAccount savingAccount = new SavingAccount();  
  25.   
  26.     //Here I need to craete the CurrentAccount object   
  27.     //to call the SavingAccount PrintData()  
  28.     CurrentAccount currentAccount = new CurrentAccount();  
  29.   
  30.     public void PrintAccounts()  
  31.     {  
  32.         savingAccount.PrintData();  
  33.         currentAccount.PrintData();  
  34.     }  
  35. }  
  36.   
  37. public class Program  
  38. {  
  39.     static void Main(string[] args)  
  40.     {  
  41.         Account account = new Account();  
  42.         account.PrintAccounts();  
  43.         Console.ReadLine();  
  44.     }  
  45. }  

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.

Dependency Injection Using Constructor, Property And Method In C# 

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#

  1. Constructor Injection
  2. Setter or property Injection
  3. Method Injection
  4. 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.

  1. //Created IAccount interface to make code loosely coupled.  
  2. public interface IAccount  
  3. {  
  4.     void PrintData();  
  5. }  
  6.   
  7. //Implemented the IAccount interface in SavingAccount class  
  8. public class SavingAccount : IAccount  
  9. {  
  10.     public void PrintData()  
  11.     {  
  12.         Console.WriteLine("Saving account data.");  
  13.     }  
  14. }  
  15.   
  16. //Implemented the IAccount interface in CurrentAccount class  
  17. public class CurrentAccount : IAccount  
  18. {  
  19.     public void PrintData()  
  20.     {  
  21.         Console.WriteLine("Current account data.");  
  22.     }  
  23. }  
  24.   
  25. //Account class is not depended on any other classes.  
  26. //So now it is loosely coupled.  
  27. public class Account  
  28. {  
  29.     private IAccount account;  
  30.   
  31.     //Passing IAccount interface as parameter to Account constructor  
  32.     public Account(IAccount account)  
  33.     {  
  34.         this.account = account;  
  35.     }  
  36.   
  37.     public void PrintAccounts()  
  38.     {  
  39.         account.PrintData();  
  40.     }  
  41. }  
  42.   
  43. class Program  
  44. {  
  45.     static void Main()  
  46.     {  
  47.         //If you want to calls the SavingAccount class PrintAccounts() method,   
  48.         //just created the object of SavingAccount() and   
  49.      //pass as parameter to Account constructor.  
  50.         IAccount savingAccount = new SavingAccount();  
  51.         Account account = new Account(savingAccount);  
  52.         account.PrintAccounts();  
  53.   
  54.         //If you want to calls the CurrentAccount class PrintAccounts() method,   
  55.         //just created the object of CurrentAccount () and   
  56.         //pass as parameter to Account constructor.  
  57.         IAccount currentAccount = new CurrentAccount();  
  58.         account = new Account(currentAccount);  
  59.         account.PrintAccounts();  
  60.         Console.ReadLine();  
  61.     }  
  62. }  

Output

Dependency Injection Using Constructor, Property And Method In C#

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.

Dependency Injection Using Constructor, Property And Method In C#

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.

  1. //Created IAccount interface to make code loosely coupled.  
  2. public interface IAccount  
  3. {  
  4.     void PrintData();  
  5. }  
  6.   
  7. //Implemented the IAccount interface in SavingAccount class  
  8. public class SavingAccount : IAccount  
  9. {  
  10.     public void PrintData()  
  11.     {  
  12.         Console.WriteLine("Saving account data.");  
  13.     }  
  14. }  
  15.   
  16. //Implemented the IAccount interface in SavingAccount class  
  17. public class CurrentAccount : IAccount  
  18. {  
  19.     public void PrintData()  
  20.     {  
  21.         Console.WriteLine("Current account data.");  
  22.     }  
  23. }  
  24.   
  25. //Account class is not depended on any other classes.  
  26. //So now it is loosely coupled.  
  27. public class Account  
  28. {  
  29.     //Here my account property is of type IAccount interface  
  30.     public IAccount account { get; set; }  
  31.   
  32.     public void PrintAccounts()  
  33.     {  
  34.         account.PrintData();  
  35.     }  
  36. }  
  37.   
  38. class Program  
  39. {  
  40.     static void Main()  
  41.     {  
  42.         //If you want to calls the SavingAccount class PrintAccounts() method,   
  43.         //just created the object of SavingAccount() and   
  44.         //assign it to IAccount interface property (i.e. account)  
  45.         Account savingAccount = new Account();  
  46.         savingAccount.account = new SavingAccount();  
  47.         savingAccount.PrintAccounts();  
  48.   
  49.         //If you want to calls the CurrentAccount class PrintAccounts() method,   
  50.         //just created the object of CurrentAccount () and   
  51.         //assign it to IAccount interface property (i.e. account)  
  52.         Account currentAccount = new Account();  
  53.         currentAccount.account = new CurrentAccount();  
  54.         currentAccount.PrintAccounts();  
  55.   
  56.         Console.ReadLine();  
  57.     }  
  58. }  

Output

Dependency Injection Using Constructor, Property And Method In C#  

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.

  1. //Created IAccount interface to make code loosely coupled.  
  2. public interface IAccount  
  3. {  
  4.     void PrintData();  
  5. }  
  6.   
  7. //Implemented the IAccount interface in SavingAccount class  
  8. public class SavingAccount : IAccount  
  9. {  
  10.     public void PrintData()  
  11.     {  
  12.         Console.WriteLine("Saving account data.");  
  13.     }  
  14. }  
  15.   
  16. //Implemented the IAccount interface in SavingAccount class  
  17. public class CurrentAccount : IAccount  
  18. {  
  19.     public void PrintData()  
  20.     {  
  21.         Console.WriteLine("Current account data.");  
  22.     }  
  23. }  
  24.   
  25. //Account class is not depended on any other classes.  
  26. //So now it is loosely coupled.  
  27. public class Account  
  28. {  
  29.     //Passing "IAccount" as parameter to PrintAccounts() method  
  30.     public void PrintAccounts(IAccount account)  
  31.     {  
  32.         account.PrintData();  
  33.     }  
  34. }  
  35.   
  36. class Program  
  37. {  
  38.     static void Main()  
  39.     {  
  40.         //If you want to calls the SavingAccount class PrintAccounts() method,   
  41.         //just created the object of SavingAccount() and directly pass as parameter   
  42.         //to Account class method (i.e PrintAccounts(new SavingAccount())).  
  43.         Account savingAccount = new Account();  
  44.         savingAccount.PrintAccounts(new SavingAccount());  
  45.   
  46.         //If you want to calls the CurrentAccount class PrintAccounts() method,   
  47.         //just created the object of CurrentAccount() and directly pass as parameter   
  48.         //to Account class method (i.e PrintAccounts(new SavingAccount())).  
  49.         Account currentAccount = new Account();  
  50.         currentAccount.PrintAccounts(new CurrentAccount());  
  51.               
  52.         Console.ReadLine();  
  53.     }  
  54. }  

Output

Dependency Injection Using Constructor, Property And Method In C#  

I hope now you are very familiar with DI and types of DI.

Happy coding.......