Introduction
A software developer writes a lot of code that is tightly coupled; and when complexity grows, the code will eventually deteriorate into spaghetti code; in other words, the application design being a bad design.
Dependency Injection (DI) is a pattern where objects are not responsible for creating their own dependencies. Dependency Injection is a way to remove hard-coded dependencies among objects, making it easier to replace an object's dependencies, either for testing (using mock objects in unit test) or to change run-time behavior.
Before understanding Dependency Injection, we should be familiar with the two concepts of Object Oriented Programming - tight coupling and loose coupling. Let's see each, one by one.
Tight Coupling
When a class is dependent on a concrete dependency, it is said to be tightly coupled to that class. A tightly coupled object is dependent on another object; that means changing one object in a tightly coupled application often requires changes to a number of other objects. It is not difficult when an application is small but in an enterprise level application, it is too difficult to make the changes.
Loose Coupling
It means two objects are independent and an object can use another object without being dependent on it. It is a design goal that seeks to reduce the inter- dependencies among components of a system with the goal of reducing the risk that changes in one component will require changes in any other component.
Now in short, Dependency Injection is a pattern that makes objects loosely coupled instead of tightly coupled. When we are designed classes with DI, they are more loosely coupled because they do not have direct, hard-coded dependencies on their collaborators. This follows the Dependency Inversion Principle(DIP).
There are three types of dependency injections,
- Constructor Dependency Injection
- Setter Dependency Injection
- Interface Dependency Injection
Dependency Inversion Principle (DIP)
It is the fifth principle of SOLID where “D” stands for Dependency Inversion Principle. Its main goal is decoupling software modules, in other words software design should be loosely coupled instead of tightly coupled. The principle states:
- High-level modules should not depend upon low-level modules. Both should depend upon abstractions.
- Abstractions should not depend upon details. Details should depend upon abstractions.
In short, the higher-level module defines an interface and lower-level module implements that interface. To explain this sentence we use a real-life example.
Suppose you are sitting on your desk. Your desk has some gadgets, like your development machine (LCD Monitor or Laptop) and mobile phone. The LCD Monitor has a cable that connects from the electric port (power cable) and the same as the mobile phone that also has a charging cable that also connects to an electric port. You could see that both devices connect from the electric port so the question occurs of who defined the port, your device or the cable? You will say that the devices define the port, in other words we don't purchase devices depending on port while the port is designed dependent on devices and the cable is just an interface that connects both devices and the port so you could say that a high-level module doesn't depend on the low-level module but both should be dependent on abstraction.
Inversion of Control (IoC) Pattern
In praticw, an application is deigned with many classes. So when we use DI with these classes then these classes are requesting their dependecies via their constructor that’s why it's helpful to have a class dedicated to creating these classes with their associated dependencies. These classes are referred to as containers, or more specifically, Inversion of Control (IoC) containers or Dependency Injection (DI) containers.
The Inversion of Control (IoC) containers is a factory that is reponsible for providing instance of types that are requested from it. If a given type has declared that it has dependencies, and the container has been configured to provide the dependency types, it will create the dependencies as part of creating the requested instance. Suppose an application designed with the Strategy design pattern. There are designed interfaces and implemented with classes. The IoC conatiner configured to such way that when application is requesting for interface then it provides that interface depedecies i.e class instance, hence class object can be provided to classes without the need for any hard-coded object construction.
ASP.NET Core and DI
The ASP.NET Core itself provides basic built in IoC container that is represented by IserviceProvider interface. It supports constructor depedency injection by default. ASP.NET Core uses DI for for instantiating all its components and services. The container is configured in ConfigureService method of the startup.cs class as this class is entry point to application. We configure the bulit-in and custome services and components that can be used in the entire application life cycle.
The ASP.NET Core services can be configured with the three lifetimes and registration options.

Figure 1: Service lifetime options
Let’s discuss the difference between these lifetime and registration options one by one.
Transient
The AddTransient method is used for the Transient lifetime option. This AddTransient method is used to register services in IoC container and it get instantiated each time when it is accessed. If we have a service which is used multiple places in same request, a new instance would be created each time.
Suppose we have a user service which is used to access user detail and user name so we create two method for these operations. One method is used in action method and another is used on view so there are two new instance create as we requeste for both methods of user service from different part controller and view.
As this method get instantiated on each request that’s why it should be used for lightweight and stateless services.
We create an interface named IUniqueKeyProviderService which has a method signature as per following code snippet.
- namespace DIApplication.Service
- {
- public interface IUniqueKeyProviderService
- {
- int GetUniqueKey();
- }
- }
Now, we create a class named UniqueKeyProviderService which has implementation of IuniqueKeyProviderService interface per following code snippet.
- namespace DIApplication.Service
- {
- public class UniqueKeyProviderService: IUniqueKeyProviderService
- {
- public int GetUniqueKey()
- {
- return GetHashCode();
- }
- }
- }




Rajeesh MenothPosted Feb 14, 2017, 4:34 AM
Awesome Article Sandeep Singh Shekhawat !!