Roadmap › SOLID Principles with Examples › Module: L, I and D
Lessons in this course (8)
5. D — Dependency Inversion Principle
Intermediate★ Must knowLesson 5 of 8
- High-level modules should not depend on low-level modules; both depend on abstractions.
- Abstractions should not depend on details; details depend on abstractions.
csharp
// ❌ High-level policy welded to a detail
public class OrderService
{
private readonly SqlOrderRepository _repo = new SqlOrderRepository(); // can't test, can't swap
}
// ✅ Depend on an abstraction owned by the high-level layer
public interface IOrderRepository { Task AddAsync(Order o); }
public class OrderService(IOrderRepository repo)
{
public Task PlaceAsync(Order o) => repo.AddAsync(o);
}
public class SqlOrderRepository(AppDbContext db) : IOrderRepository
{
public async Task AddAsync(Order o) { db.Orders.Add(o); await db.SaveChangesAsync(); }
}
// Composition root (Program.cs)
builder.Services.AddScoped<IOrderRepository, SqlOrderRepository>();
builder.Services.AddScoped<OrderService>();DIP vs DI vs IoC:
- DIP — the principle (depend on abstractions).
- IoC (Inversion of Control) — the general idea that a framework/container controls object creation and flow, not your code.
- DI (Dependency Injection) — the technique: dependencies are passed in (constructor, method or property injection), usually by an IoC container.