Dependency injection in ASP.NET Core

Why DI exists, how to register services, the three lifetimes, and the mistakes interviewers ask about.

Dependency injection in ASP.NET Core

The idea

A class shouldn’t create the things it depends on. It asks for them in its constructor, and something outside provides them. That something is the DI container.

IEmailSender sender = new ConsoleEmailSender();
var orders = new OrderService(sender);
orders.PlaceOrder("book");

interface IEmailSender { void Send(string text); }
class ConsoleEmailSender : IEmailSender { public void Send(string text) => Console.WriteLine(text); }
class OrderService(IEmailSender sender)
{
    public void PlaceOrder(string item) => sender.Send($"Ordered: {item}");
}

It prints Ordered: book. The demo wires the objects by hand; in ASP.NET Core the container does it. Swap ConsoleEmailSender for a fake in a unit test, and OrderService doesn’t change.

Registering services

In Program.cs, tell the container which class to use for each interface:

  • builder.Services.AddTransient<IClock, SystemClock>();
  • builder.Services.AddScoped<IOrderRepository, SqlOrderRepository>();
  • builder.Services.AddSingleton<ICache, MemoryCache>();

Controllers, minimal API handlers and other services then just list what they need in their constructors or parameters.

The three lifetimes

Lifetime One object per… Typical use
Transient every time it is asked for (resolved) small stateless helpers
Scoped HTTP request DbContext, unit of work
Singleton whole app caches, configuration, clients meant to be shared

Mistakes interviewers ask about

  • Captive dependency (a longer-lived service holding a shorter-lived one): a singleton that takes a scoped service in its constructor keeps it for the whole app. A DbContext shared by all requests is not thread-safe and breaks.
  • new inside the class: creating dependencies with new hides them and makes testing hard.
  • Too many constructor parameters: a sign the class does too much.

Read more: https://roadmap.sh/aspnet-core

#tip · TIP-047


Write a comment