Get Started With the Dependency Injection Principle in ASP.Net

5.00 avg. rating (97% score) - 1 vote

Topics Covered

  1. Introduction
  2. Dependency Inversion Principle
  3. Bob Martin’s Discovery
  4. Inversion of Control
  5. Service Locator
  6. Dependency Injection
    • Constructor Injection
    • Setter Injection
    • Interface Injection
  7. Demo

Introduction

concept
How is this concept relevant? Let’s have a look at the traditional architecture generally followed in MVC applications.

traditional architecture

In this architecture, we can see that each of the layers depends on the other layer beneath it. That is why we can say in a technical manner that they are coupled with each other. However, coupling is necessary for every application. Then what is the need for dependency injection, if coupling is necessary? Are we contradicting ourselves? No, we are not. Coupling is necessary, but tight coupling is a big threat to project/application maintainability and performance. Thus, for always having loose coupling or minimal dependency, we require the concept “Dependency Injection”.

In the preceding figure, we see the View layer (UI) has a dependency on the Business Logic Layer that also has a dependency on the Data Layer, thus there is a transitive dependency, but they are still dependencies. Let’s get deeper into what these dependencies mean in real scenarios and how to resolve them.

Dependency Inversion Principle

Quote:

High-Level Modules should not depend upon lower-level modules, rather both should depend upon abstractions.

Now what does that mean? Let me explain this using an example.

In real life, consider our day-to-day chargeable portable devices that we use, like mobile devices, torches, radios and so on. Do these devices have similar charging ports? No, they do not. We need to plug in various chargers for each device. Now wonder if all the devices had similar charging ports, we could use a single charger for each device. This defines the preceding quote. Still in doubt? Okay, let’s look at the figure below:

Dependency Inversion Principle

You can see that the figure on the left has a High-Level Module dependent on the interface, also the Low-Level Module is coupled to the interface. Here, only one Low-Level Module exists, so it seems Okay, but in actual applications this is not the case, there may be many Low-Level Modules. Then, if there are so many Low-Level Modules (LLMs) and their associated High-Level Modules (HLM) will have dependency on the interface then it is a threat.

But have a look at the diagram on the right, we can see there is just a single interface and a high-level module and many low-level modules will interact with the interface, here the HLM has the interface and that can be reused and the previous dependency of the HLM on the LLM is avoided. In a more simpler way, instead of a Low-Level Module defining the interface, on which the High-level Module depends on, in the Dependency Inversion Principle, the HLM defines the interface and the LLMs implement the members. This is done using a common interface or an abstract class.

Bob Martin’s Discovery

Bob Martin, commonly known as Uncle Bob, is the founder of the famous SOLID principles, of which Dependency Injection is a part. He explained the concept with a very nice and famous “Copy Read and Write” example.

According to him, a HLM should never depend on the LLM, rather they should have common abstractions. The example that he provided was:

Bob Martin

In that figure, suppose there is a copy and there are two methods, Read and Write. Thus the copy module calls the two modules. Now suppose another Write method comes for Write to Disk. Suppose again that we implement the copy method, similarly for the Read method also Read from the keyboard and Read from a TouchPad. This increases the dependency and coupling. So, to avoid that, we can have a common method for Copy that is Read and Write that will be reused by each device from which the read and write would be called respectively.

Here, the Read and Write acts as an abstract classes, since the Copy now does not depend upon whether the future request is a keyboard, a touchpad or a printer or disk.

Thus, the principle of dependency inversion is at the root of many of the benefits claimed for object-oriented technology. Its proper application is necessary for the creation of reusable frameworks. It is also critically important for the construction of code that is resilient to change. And, since the abstractions and details are all isolated from each other, the code is much easier to maintain.

Inversion of Control

Inversion of Control is a style of programming, that has a framework controlling the flow of the application, that is we are trying to change the normal flow or inverse the flow to avoid tight coupling. It works on the Dependency Inversion Principle. This IOC is not only associated with the DIP but is also associated with the Dependency Injection and Service Locator.

Inversion of Control

IoC is a way to provide abstraction. A way to change the control. IoC gives some ways to implement DIP. If you want to make a higher-level module independent from the lower-level module then you need to invert the control so that the Low-Level Module is not controlling the interface and the creation of the object. Finally IoC gives some way to invert the control.

Service Locator

Service Locator also implements the DIP principle and indeed provides us with loosely coupled code. This introduces a locator object, that is used to resolve dependencies within a class. Client uses the locator to find and access the services implemented using the interface. Let’s see that with a code example.


 

Dependency Injection

Dependency Injection is a type of Inversion of Control, where we move the creation and binding of a dependency to outside of the class, that uses the dependency to access the implemented members of the common interface. This means it is done without any interference of any object, generally by a component that passes constructor parameters and the properties. As without any DI resolves like Ninject, Unity and so on, if we try to invoke the contractor of a class with a parameter, we are thrown an error as:

Quote: No parameter less constructor defined for this object.

Some of the advantages of using Dependency Injection are:

  • Reduces Class Coupling.
  • Increases Reusability.
  • Improves the maintainability for future purposes.
  • Improves and catalyses the Unit testing process.

Dependency Injection

Constructor Injection

Constructor Injection is the most commonly used form of Dependency Injection. As the name suggests, it uses injection into the class level using its constructor. Let’s see a sample code snippet for better understanding:


 

The preceding code snippet explains the flow. First, we create the dependency by creating the department object for the CheckDepartment() member whose implementation would be used by the class using dependency, that is when we are creating the new instance of the class and passing the dependency. The drawback here may be we cannot create the class and use it without/before passing in the dependency, since we had only the constructor, that would need the dependency.

Setter Injection

Here, we create a setter on the dependent class and use the same setter as a property to set the dependency. In this there is a flexibility to change/set the dependency, since we are the one setting it and in setter injection. Unlike constructor injection we can instantiate the class without passing the dependency. We could set that after instantiating the class also. The code snippet for the setter injection goes as follows in the simplest manner:


 

Interface Injection

This is also used less in real applications. It is the same as the Setter injection but here, the Dependent class implements the interface. The injector then uses the interface to set the dependency. Interface then defines a method that would be called to do the dependency. Let’s look into the code snippet:


 

This is similar to a Setter but the difference is that in a Setter we do not get to understand what goes on in the background since we just set the dependency using the setter, but here we know the dependency is coming from the interface after implementing it in the dependent class. Here, after typecasting the employee to the IDepartmentForInject type we are invoking the Inject method.

Demo For Manual Injection

The following is a small demo console application to show dependency injection. You can find the code for download also.


 

The values in the Autos window in Visual Studio shows how the _department, dependency set in the constructor, has the value from the CheckDepartment that implements IDepartment.

CheckDepartment

The result that comes is the string returned:

result

Points of Interest

There are many dependencies resolvers available in Nuget as DLL packages like, Ninject, Unity, StructureMap3, Castle Windsor. But understanding the details of how the background works would be fruitful for using the tools. This is now commonly used and is a confusing topic. I hope this helps anyway. 🙂

References:
CP Article
DotNet Tricks
MSDN