In simple terms, Dependency Injection (DI) is a pattern that allows you to inject dependencies (like services or repositories) into classes instead of having those classes create the dependencies themselves. This means your classes are more modular, easier to test, and less tightly coupled.
.NET Core makes DI super easy with its built-in Microsoft.Extensions.DependencyInjection library. It’s ready to go out of the box and handle most of your dependency management needs.
Why Should You Use Dependency Injection in .NET?
Here are the top reasons why DI is a game changer in .NET:
- Better Modularity
When you decouple your components using DI, it becomes way easier to swap things out — whether that’s replacing a service or updating a database connection. - Easier Unit Testing
DI allows you to inject mock services into your classes. This makes testing a breeze since you don’t have to depend on real databases, APIs, or external services. - Improved Maintainability
Since dependencies are injected, you don’t have to worry about changing classes every time you tweak something. It reduces tightly coupled code and makes refactoring easier.
How Do You Set Up Dependency Injection in .NET?
Getting started with DI in .NET is pretty straightforward. You’ll typically configure your services in the Startup.cs or Program.cs file.
Here’s a quick breakdown:
1. Register Your Services
In the ConfigureServices method, you register your services with a DI container:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IMyService, MyService>(); // Register MyService with DI container
services.AddControllers();
}
2. Injecting Services into Controllers
Now, when you need a service inside a controller, you inject it through the constructor:
public class MyController : ControllerBase
{
private readonly IMyService _myService;
public MyController(IMyService myService)
{
_myService = myService;
}
public IActionResult Get()
{
var result = _myService.GetData();
return Ok(result);
}
}
The IMyService dependency will be automatically injected by the DI container when MyController is instantiated.
Understanding DI Lifetimes in .NET:
In .NET, you can configure your services to have different lifetimes. There are three main types of service lifetimes:
1. Transient:
A new instance of the service is created every time it’s requested.
services.AddTransient<IMyService, MyService>();
2. Scoped:
A new instance is created per request (useful for things like HTTP requests).
services.AddScoped<IMyService, MyService>();
3. Singleton:
A single instance is used throughout the entire application’s lifetime.
services.AddSingleton<IMyService, MyService>();
Constructor Injection: The Most Common DI Technique
The most popular way to use DI in .NET is constructor injection. You simply define the dependencies in the class constructor, and the DI container will take care of providing them.
Here’s a quick example:
public class MyService: IMyService
{
private readonly IDataRepository _dataRepository;
// Constructor Injection
public MyService(IDataRepository dataRepository)
{
_dataRepository = dataRepository;
}
public void DoWork()
{
_dataRepository.SaveData();
}
}
In this example, IDataRepository is injected into MyService through the constructor.