How do you register and resolve multiple implementations of the same interface in ASP.NET Core DI?

ASP.NET Core Dependency Injection Advanced 3–5 Yrs5+ Yrs Coding 1 min read

Quick Answer

Register each implementation against the interface; the container collects them. Inject IEnumerable<INotifier> to get all of them, or use keyed services (.NET 8+) — AddKeyedScoped<INotifier, EmailNotifier>("email") and [FromKeyedServices("email")] — to resolve a specific one. Resolving INotifier plainly gives you the last registered.

If I register two implementations against INotifier, the container keeps both — resolving INotifier directly just gives me the last one registered, but injecting IEnumerable<INotifier> gives me all of them, which is what I want for something like sending a notification through every channel. If I need to pick a specific one, .NET 8 has keyed services: I register with a key and consume it with [FromKeyedServices("email")]. Before .NET 8 I'd inject a factory delegate or write a small resolver that switches over the IEnumerable.

  • All of them: services.AddScoped<INotifier, EmailNotifier>(); services.AddScoped<INotifier, SmsNotifier>(); then inject IEnumerable<INotifier> and loop — good for a notification fan-out or a validation pipeline.
  • A specific one by key (.NET 8+): AddKeyedScoped<INotifier, EmailNotifier>("email"); consume with [FromKeyedServices("email")] INotifier n or sp.GetRequiredKeyedService<INotifier>("email").
  • Pre-.NET 8: a factory delegate (Func<string, INotifier>) or a small resolver class that switches over the injected IEnumerable.
  • TryAddEnumerable registers an implementation only if that exact type isn't already registered — useful in libraries.

C# — fan-out + keyed
// all implementations
builder.Services.AddScoped<INotifier, EmailNotifier>();
builder.Services.AddScoped<INotifier, SmsNotifier>();

public class AlertService(IEnumerable<INotifier> notifiers)
{
    public Task RaiseAsync(Alert a) =>
        Task.WhenAll(notifiers.Select(n => n.SendAsync(a)));
}

// a specific one (.NET 8+)
builder.Services.AddKeyedScoped<INotifier, EmailNotifier>("email");
public class Welcome([FromKeyedServices("email")] INotifier email) { }