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 increasecode 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 arerequired to do their work.Loosely coupled code increases the modularity of application which offers usgreater reusability, maintainability, and testability.

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.

Output

The output of above implementation will be,

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,

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.

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.

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.

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.

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.

.NET Developer at Virtual Employee with an experience of more than 2 years in multiple web and windows based technologies. Worked on the applications build for the Educational domain, Manufacturing domain, and Capital Market.