A class receives its dependencies from outside (usually through the constructor) instead of creating them with new.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | // ====================================================================== // Q: What is Dependency Injection and why do we use it? // // A class receives its dependencies from outside (usually through the // constructor) instead of creating them with new. It is how Inversion of Control // is implemented. ASP.NET Core has a built-in container // (Microsoft.Extensions.DependencyInjection). Benefits: loose coupling, // testability (fakes / mocks), all the wiring in one place (composition root = // Program.cs), and the container manages lifetimes (see Q5). // - Service Locator (IServiceProvider.GetService inside business logic) is an // anti-pattern: it hides dependencies. // - A constructor with 7-8+ dependencies signals that the class does too much // (an SRP violation). // - Use TimeProvider (.NET 8) instead of DateTime.UtcNow, so tests can use // FakeTimeProvider. // - DI is not DIP: DI is the mechanism, DIP (Q18) is the principle. // ====================================================================== // WRONG: tight coupling, cannot be tested without a real ERP public class OrderService { private readonly ErpClient _erp = new ErpClient(new HttpClient()); } // RIGHT: constructor injection (primary constructor, C# 12) public class OrderService(IOrderRepository orders, IErpClient erp, TimeProvider clock) : IOrderService { public async Task SubmitAsync(int orderId, CancellationToken ct) { /* ... */ } } // Composition root: Program.cs builder.Services.AddScoped<IOrderService, OrderService>(); builder.Services.AddScoped<IOrderRepository, EfOrderRepository>(); builder.Services.AddSingleton(TimeProvider.System); // testable time builder.Services.Configure<ErpOptions>(builder.Configuration.GetSection("Erp")); // Options pattern builder.Services.AddKeyedScoped<IShippingCalculator, DhlCalculator>("dhl"); // keyed services (.NET 8) |