Dependency Injection (DI)

লেসন ১৯ / ৫০

DI কী?

Dependency Injection — class নিজে dependency তৈরি করে না, বাইরে থেকে পায়। ASP.NET Core এ built-in।

Without DI ❌

public class UserController {
    private UserService _service = new UserService(new SqlDb());
    // tightly coupled, untestable
}

With DI ✅

public interface IUserService {
    Task<User> GetAsync(int id);
}

public class UserService : IUserService {
    private readonly AppDbContext _db;
    public UserService(AppDbContext db) => _db = db;    // injected!
    public Task<User> GetAsync(int id) => _db.Users.FindAsync(id);
}

[ApiController]
public class UsersController : ControllerBase {
    private readonly IUserService _service;
    public UsersController(IUserService service) => _service = service;
    // ⬆ constructor injection
}

Service Lifetimes ⭐

LifetimeScopeব্যবহার
Singletonapp-wide একটি instanceconfig, cache
Scopedper HTTP requestDbContext, repositories ⭐
Transientপ্রতি injection-এ নতুনlightweight services
// Program.cs
builder.Services.AddSingleton<IClock, SystemClock>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddTransient<IEmailSender, EmailSender>();

// Or instance
builder.Services.AddSingleton(new MyConfig { Key = "..." });

// Factory
builder.Services.AddScoped<IRepo>(sp => new Repo(sp.GetRequiredService<Db>()));

Built-in Services

// AddControllers, AddDbContext, AddHttpClient, AddLogging,
// AddMemoryCache, AddDistributedRedisCache, AddAuthentication...

builder.Services.AddDbContext<AppDbContext>(opt =>
    opt.UseSqlServer(connStr));   // Scoped by default

builder.Services.AddHttpClient<ExternalApiClient>(c => {
    c.BaseAddress = new Uri("https://api.example.com");
});

Resolving

// 1. Constructor (preferred)
public class Foo(IBar bar) { }    // primary constructor (C# 12)

// 2. From HttpContext
var svc = HttpContext.RequestServices.GetService<IUserService>();

// 3. Service Locator (avoid)
var svc = app.Services.GetRequiredService<IUserService>();

⚠️ Common Pitfalls

  • Captive dependency — Singleton-এ Scoped inject করবেন না (DbContext crash)।
  • Disposable — Scoped/Transient-এর Dispose() automatically call হয়।