What is Dependency Injection?
In software engineering, dependency injection is a technique whereby one object (or static method) supplies the dependencies of another object. A dependency is an object that can be used as a service.
An injection is the passing of a dependency on a dependent object (a client) that would use it. The service is made a part of the client’s state, passing the service to the client, rather than allowing a client to build or find the service, which is the fundamental requirement of the pattern.
In this article, we only focus on how to achieve constructor injection (Dependency Injection), not its lifetime and Service lifetimes and registration options.
ASP.NET Core applications can leverage built-in framework services by having them injected into methods in the Start-up class, and application services can be configured for injection as well. The default services container provided by ASP.NET Core provides a minimal feature set and isn’t intended to replace other containers.
Types of Dependency Injection
- Constructor Injection
- Property Injection (Setter Injection)
- Method Injection
Why should we use DI in our Application?
- High-level modules should not depend on low-level module.
- Reduces class coupling.
- Improves code maintainability.
- Improves application testing.
What is Constructor Injection?
Constructor injection (DI) is a technique for achieving loose coupling between objects and their collaborators or dependencies. Rather than directly instantiating collaborators, or using static references, the objects a class needs to perform its actions are provided to the class in some fashion. Most often, classes will declare their dependencies via their constructor, allowing them to follow the Explicit Dependencies Principle. This approach is known as “constructor injection”.
Steps to achieve Constructor injection in Asp.Net Core 2.1 App-
- Create Interface for Service
- Create Service class inherited with the interface
- Inject Service to Startup.cs File
- Inject Service in our client class
Create Interface for Service-
In this step, we create an Interface for service, which contains all the method we need in client class. First, we create a Folder named Interfaces in our solution, by right click on solution and Add window. Now add public interface containing all method.
Create Service class inherited with the interface-
In this step, we create a class (service class) which will inherit our created interface. Add a folder name Services (any name you want). Create a public class which implements all methods of previously created interface. Add your desired logic in your class as follows-
Inject Service to Startup.cs File-
In this, we register your own application services with the help of the ConfigureServices method in startUp.cs file having IserviceCollection as its parameter. IserviceCollection specifies the contract for a collection of service descriptors. The AddScoped method of IserviceCollection, is used to map abstract types to concrete services that are instantiated separately for every object that requires it. It’s important to choose an appropriate lifetime for each of the services you register. Should a new instance of the service be provided to each class that requests it? Should one instance be used throughout a given web request? Or should a single instance be used for the lifetime of the application?
Inject Service in our Client Class-
After registering a service in startup.cs file, it’s time to use it in our concrete class. We will create one property of Interface type and pass it to the concrete class constructor as follows-
Constructor injection requires that the constructor in question be public. Otherwise, your app will throw an Invalid Operation Exception:
Constructor injection requires that only one applicable constructor exist. Constructor overloads are supported, but only one overload can exist whose arguments can all be fulfilled by dependency injection. If more than one exists, your app will throw an Invalid Operation Exception:
Multiple constructors accepting all given argument types have been found in type ‘YourType’. There should only be one applicable constructor.
Constructors can accept arguments that are not provided by dependency injection, but these must support default values. For example:
As we can see our HomeController class does not directly dependent upon StudentRepo class, It is loosely coupled with it with help of DI. In this, I am not using any DB or framework to fetch data from DB. We can any time create a class, which inherited the IStudentRepo, and having EntityFramework feature to fetch data from Db. And then no major changes in concrete class, we just make a change in startup.cs file so that application with return data from DB, not any mock data.
There is no need to newing of service class because our class does not directly depend upon it.