.NET › Dependency Injection

How do you register multiple implementations of the same interface, and how do you resolve all of them together?

Intermediate

Answer

Calling AddScoped/AddSingleton/AddTransient multiple times for the same interface with different implementations registers all of them; injecting IEnumerable<TInterface> resolves the full collection of registered implementations in registration order, useful for patterns like a chain of validators or multiple notification channels that should all run.
builder.Services.AddScoped<INotifier, EmailNotifier>();
builder.Services.AddScoped<INotifier, SmsNotifier>();
builder.Services.AddScoped<INotifier, PushNotifier>();

public class NotificationService {
    private readonly IEnumerable<INotifier> _notifiers;
    public NotificationService(IEnumerable<INotifier> notifiers) => _notifiers = notifiers;

    public async Task NotifyAllAsync(string message) {
        foreach (var notifier in _notifiers) await notifier.SendAsync(message);
    }
}
Real-world example An order confirmation feature registers Email, SMS, and Push notification implementations of INotifier, then injects IEnumerable<INotifier> to fan out a single order-confirmed event to every configured notification channel simultaneously.

Common follow-ups: How do you resolve just the LAST registered implementation instead of all of them?;How does keyed services (added in .NET 8) provide a more explicit alternative to this pattern?