How to implement Dependency Injection in C#?

Problem Scenario

Objects can be loosely or tightly coupled. Tightly coupled objects have dependencies on concrete objects due to which they have lower reusability, maintainability, and testability. Tightly coupled object provide lesser dynamicity due to which user need to change the implementation of class and it’s member functions. We can achieve this via Dependency Injection.

What Dependency Injection do? 

Irrelevant dependencies increase code complexity which results in increased loading and execution time of application. Dependency Injection (DI) is a solution design which provides development of the loosely coupled code. ‘Loose Coupling‘ means the object will only have those dependencies which are required to do their work. Loosely coupled code increases the modularity of application which offers us greater reusability, maintainability, and testability. 

Note: For more details on loosely coupled coding guidelines, please follow Dependency Inversion Principle.

Types of Dependency Injection

1. Constructor Injection:  It uses parameters to inject dependencies. The object has no defaults or single constructor due to which specified values are required at the time of creation to instantiate the object. This is the most common type of DI. We can use injected component anywhere in the class. It makes a strong dependency contract. In this type, we can make dependency immutable in order to prevent it from circular dependency. For entire dependency graph, it requires up-front wiring which needs a public constructor in the class to pass dependency as a parameter.

Example

Consider a scenario, where a student took admission in school and school provides bag, dress, books etc to that student. Here, the student does not like to receive goodies from different counters. What the student would like, that he/she should receive all the goodies from a single counter in one go.

Create a console application of any name and create two classes.

Dependency Injection

In above image,[mk_highlight text=”SchoolBag” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] and[mk_highlight text=”SchoolDress” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] are the basic ‘Service classes’ having [mk_highlight text=”Bag” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] and [mk_highlight text=”Dress” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] methods respectively.

In the image below,[mk_highlight text=”Student” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] class is ‘Client class’ using the service (i.e. [mk_highlight text=”SchoolBag” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”]) and assigning that[mk_highlight text=”bag” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”]to ‘John’ in the[mk_highlight text=”main” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] program.

Dependency Injection

The[mk_highlight text=”Student” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] constructor is assigning a[mk_highlight text=”new” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] instance of[mk_highlight text=”SchoolBag” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] class. And the[mk_highlight text=”Assign” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] method is acting like a[mk_highlight text=”Service_Start()” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] method. It is receiving the[mk_highlight text=”studentName” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] from the[mk_highlight text=”main” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] program and passing it to[mk_highlight text=”Bag” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] method of[mk_highlight text=”SchoolBag” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] class.

Output

The output of above implementation will be,

Dependency Injection

Above implementation has one issue i.e. we only managed to assign[mk_highlight text=”SchoolBag” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”]to the[mk_highlight text=”Student” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”].[mk_highlight text=”SchoolDress” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”]is still left or what if we want to provide some other things to the student. Since the object of[mk_highlight text=”SchoolBag” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”]is created inside the Student class’s constructor, we have to modify the implementation of Student class for[mk_highlight text=”SchoolDress” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”]and the for some other thing, which is not a proper implementation. This is a type of concrete dependency. To avoid this, we can use interfaces to provide a level of indirection. See the below implementation.

Implementing Interface

Create a service interface.

interface IThings 
  { 
      void Assign(string studentName); 
  }

and now remove the previous implementation of the service classes (i.e.[mk_highlight text=”SchoolBag” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] and [mk_highlight text=”SchoolDress” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”]) and implement the above service interface in the service classes. Like this,

Dependency Injection

After this, we need to alter our client class. We need to “inject” a parameter of service interface type (i.e.[mk_highlight text=”IThings” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”]) in the constructor of[mk_highlight text=”Student” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] class.

Dependency Injection

In above image, we have injected a new object into the client class. And we can use this object anywhere in the client class. Below is the respective output.

Dependency Injection

Source Code

Below is the full source code.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
namespace DependencyInjection 
{ 
    interface IThings 
    { 
        void Assign(string studentName); 
    } 
  
    class SchoolBag : IThings 
    { 
        public void Assign(string studentName) 
        { 
            Console.WriteLine("{0} recieved Bag", studentName); 
        } 
    } 
  
    class SchoolDress : IThings 
    { 
        public void Assign(string studentName) 
        { 
            Console.WriteLine("{0} recieved Dress", studentName); 
        } 
    } 
  
    class Student 
    { 
        private IThings thing; 
        public Student(IThings iThing) 
        { 
            thing = iThing; 
        } 
        public void Recieve(string studentName) 
        { 
            thing.Assign(studentName); 
        } 
    } 
  
    class Program 
    { 
        static void Main(string[] args) 
        { 
            Student obj1 = new Student(new SchoolBag()); 
            obj1.Recieve("John"); 
  
            Student obj2 = new Student(new SchoolDress()); 
            obj2.Recieve("John"); 
  
            Console.ReadLine(); 
        } 
    } 
}

2. Setter or Property Injection: In this, we don’t require to change the constructor. We pass dependencies through the exposed public properties. In this, we can create costly resources or services as late as possible and only when required.  It is difficult to identify which dependencies are required and it is beneficial to perform null checks in setter properties. For entire dependency graph, it does not require up-front wiring.

In addition to our previous code, the implementation we did for[mk_highlight text=”Student” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] constructor has now been transferred to the setter of[mk_highlight text=”SetStudent” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] property. And the new object which was previously passed as a parameter in the constructor of[mk_highlight text=”Student” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] class, has now been assigned to the [mk_highlight text=”SetStudent” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] property in the[mk_highlight text=”main” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] program. The output will be same as it was for constructor injection. See the following image.

 

Dependency Injection

3. Method Injection: In this, the dependency is been injected within a single method to be used by that method only. It is useful in case when only one method needs dependency, not the whole class.

In addition to our previous code, the implementation we did for setter property has now been transferred to the[mk_highlight text=”Assign” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] method and the dependency has been injected as a parameter from[mk_highlight text=”main” text_color=”#520909″ bg_color=”#ffffff”  font_family=”Consolas”] program. The output will be same as it was for property injection. See the following image.

 

Dependency Injection

Conclusion

With DI, you can inject extra code between the conditions. To illustration, you can utilize the Constructor Injection to give an instance its conditions. In the event that you have a class with ten functions that have no dependencies. Then, you have to include one or more than one function with a dependency. You can change the constructor to utilize Constructor Injection.

Then again, you can basically include another constructor that takes the dependency as a parameter. However, in the event that there is a dependency which is costly to make, you can utilize the Setter Injection. It gives you a chance to make the expensive resources only when required. As should be obvious, DI makes code testable, viable, reusable and coherent.

Leave a Comment