Dependency Injection
DI is a technique in software development that manages the dependencies between different components or modules in the system.
This is done by providing a component with its required dependencies from an external source instead of allowing it to create or manage its dependencies.
Inversion of Control (IoC)
It is a design pattern that allows the flow of control in a program to be inverted or reversed. Instead of the program controlling the flow of execution, the flow is controlled by an external framework or container.
So, Why should we use IoC?
By applying IoC, an application can decouple its components, making them more modular and easier to test and maintain.
IoC promotes the uses of interfaces and abstraction which makes the code more flexible and extensible.
Types of DI
Constructor Injection
This involves injecting dependencies through a class's constructor. This is the most common form of DI and is often used when a class has mandatory dependencies that it needs in order to function correctly.
Property Injection
This involves injecting dependencies through a class's public properties. Property injection is less common than Constructor injection and is often used when you need to inject optional dependencies.
Method Injection
This involves injecting dependencies through a method call. Method injection is the least common form of DI and is often used when a dependency is only required for a specific method call.
DI in .NET Core
DI in .NET core is a built-in feature that allows you to separate the creation of object graphs from your application code.
To Use DI, you need to register your services with a service container by specifying which services your application needs and how to create them.
Lifetime Management
Lifetime management in Dependency injection refers to the way in which instances of a service are created and managed by the Dependency Injection container. In other words, it determines the lifespan of an object created through Dependency Injection.
The three-lifetime management options are as follow:
Transient
Scoped
Singleton
Transient Method
This is the default lifetime management in the .NET core. A new instance of the service is created each time it is requested from the container.
Methods
AddTransient: Registers a service with transient lifetime management.
Add Transient<TService, TImplementation>: Registers a service and its implementation with transient lifetime management.
When you have a lightweight and stateless service that does not maintain any state between requests, such as a logger or a helper class. When you want to ensure that a new instance of the service is created every time it is requested from the container. This can help prevent issues with thread-saÿety or shared state.
Scoped Method
A single instance of the service is created for each scope. A scope typically corresponds to a web request in a web application.
Methods
AddScoped: Registers a service with the scoped lifetime management. AddScoped<TService, TImplementation>: Registers a service and its implementation with the scoped lifetime management.
When you have a service that needs to maintain a state between requests, but that should not be shared.
Singleton Method
A single instance of the service is created and shared throughout the lifetime of the application. This can be useful for services that are expensive to create or for services that need to maintain state.
Methods
AddSingleton: Registers a service with singleton lifetime management.
AddSingleton<TService, TImplementation>: Registers a service and its implementation with the singleton lifetime management.
Be aware that a single instance of the service will be created and shared throughout the lifetime of the application. This can lead to issues with shared state or thread safety if the service is not designed to be used in this way. Be sure to handle any concurrency issues that may arise when using a singleton.