MSDN Documentation

Dependency Injection in ASP.NET Core

Dependency Injection (DI) is a powerful design pattern that promotes loose coupling and makes applications more maintainable and testable. ASP.NET Core has a built-in DI container that simplifies the implementation of this pattern.

What is Dependency Injection?

Instead of a component creating its own dependencies (objects it needs to function), those dependencies are "injected" into it, typically through its constructor, a property, or a method. This allows the component to be oblivious to how its dependencies are created and managed.

The ASP.NET Core DI Container

ASP.NET Core includes a lightweight, built-in DI container that handles:

Registering Services

You register services in the ConfigureServices method of your Startup.cs file (or using Minimal APIs). The DI container supports three primary lifetime modes:

Here's an example of registering services:


public void ConfigureServices(IServiceCollection services)
{
    // Register a service with a singleton lifetime
    services.AddSingleton<IMyService, MyService>();

    // Register a service with a scoped lifetime
    services.AddScoped<IOtherService, OtherService>();

    // Register a service with a transient lifetime
    services.AddTransient<IAnotherService, AnotherService>();

    services.AddControllersWithViews();
}
            

Resolving Dependencies

Dependencies are typically resolved through constructor injection. The DI container automatically provides instances of registered services when an object is created.

Example of a controller that uses constructor injection:


public class HomeController : Controller
{
    private readonly IMyService _myService;
    private readonly IOtherService _otherService;

    public HomeController(IMyService myService, IOtherService otherService)
    {
        _myService = myService ?? throw new ArgumentNullException(nameof(myService));
        _otherService = otherService ?? throw new ArgumentNullException(nameof(otherService));
    }

    public IActionResult Index()
    {
        ViewBag.Message = _myService.GetData();
        return View();
    }
}
            
It's good practice to inject interfaces rather than concrete implementations to maintain loose coupling.

Service Lifetime Considerations

Choosing the correct service lifetime is crucial for performance and correctness.

When a service with a shorter lifetime (e.g., transient) is injected into a service with a longer lifetime (e.g., singleton), the DI container might create a single instance of the shorter-lived service and reuse it, which can lead to unexpected behavior. Be mindful of these lifetime dependencies.

Built-in Services

ASP.NET Core provides many built-in services that you can inject, such as:

Custom DI Container

While the built-in container is powerful and sufficient for most applications, you can integrate with third-party DI containers like Autofac, Ninject, or StructureMap if you require more advanced features.