Introduction
Dependency Injection (DI) is a vast topic but here we will concentrate only on asp.net core implementation. We will go through the one basic, most widely used way to inject dependencies, we will see how to manually inject IServiceProvider, and then we will see multiple ways to inject your services.
The objective of this blog is to provide a reference material where the developers can glance through it, to just remember the key points while doing development. If you want the author to elaborate on any specific section then feel free to leave a comment and we will try to create a dedicated blog on it.
Dependency Injection
A dependency is an object that another object depends on. There are three basic ways to inject dependencies, namely:
- Constructor injection
- This is the most widely used way to inject dependencies in asp.net core.
- In this blog we will concentrate only on this injection.
- Setter injection
- Interface injection
asp.net core includes a very simple built-in DI container, which supports constructor injection, so to make a service available for the container, you have to add it within the ConfigureServices method of the Startup class.
If you have created any custom service then you have to do the same thing for your custom services i.e. you have to declare them within ConfigureServices method.
Below is the sample snippet :
public void ConfigureServices(IServiceCollection services) {
services.AddScoped<IMyDependency, MyDependency>();
services.AddRazorPages();
}
Note: Create a folder in the main project structure, call it Services, add your service class, and then extract the interface out of it (using Visual Studio 2019 feature).
Lifetime and registration options
There are multiple ways of injecting your services, and you need to choose which one best suits your needs:
1. Transient injection
Creates an instance every time the method is called. e.g., stateless services:
services.AddTransient<IMyService, MyService>();
2. Scoped injection:
Creates an instance, once per request pipeline. e.g., stateful services:
services.AddScoped<IMyService, MyService>(); 3. Singleton injection:
Creates one single instance for the whole application:
services.AddSingleton<IMyService, MyService>();
Using IServiceProvider to create needed object
This is useful in a scenario wherein you are not able to inject the dependency then you can instead inject IServiceProvider and use it to create the instance manually.
The example of above scenarios is BackgroundService, it supports only Single instances as this service itself is Singleton, so in this scenario your code will not compile if you try to pass the dbContext in the constructor of BackgroundService, as dbContext is Scoped by default, and we should not try to make it Singleton. In this case one of the solutions is to make use of IServiceProvider in the constructor and alter use it to create instance of dbContext.
Here is the example to make the above concept more clearer.
First the ServiceProvider instance.
public MyBackgroundService(ILogger<MyBackgroundService> logger, IServiceProvider provider) { _logger = logger;
_provider = provider;
}
Use the ServiceProvider instance to manually create the service.
// Using statement - this is needed for 'CreateScope' method using Microsoft.Extensions.DependencyInjection;
// Snippet which will be part of your method
using(var scope = _provier.CreateScope()) {
var dbContext = scope.ServiceProvider.GetRequiredService<CacheContext>();
dbContext.AddRange(MyCollection);
dbContext.SaveChanges();
}
Summary
The objective of this blog was to provide a reference material, this is not meant to be used, to learn DI in asp.net core, rather as a lookup or cheat-sheet to quickly refer the importance concepts.
Related Topics
Project Structure
References
Your feedback
Your feedback is of paramount importance to us, provide your valuable inputs; what else you would like to read about, or if you would like the author to elaborate on any specific topic from this article, or any other article on this blog.
Disclaimer
The material presented in this blog is to help educate the developers, and the author(s) & owner(s) of this blog are not responsible of any damage arising out of use of the code snippets or any other contents of this blog.
Comments
Post a Comment