Skip to content
AgileLogics
5 min read

Dependency Injection

Prerequisites: Reflection & attributes

Rather than a class constructing its own dependencies directly, they are provided ("injected") from outside — usually through the constructor — making the class easier to test and reconfigure.

interface IEmailSender {
    void Send(string to, string message);
}

class OrderService {
    private readonly IEmailSender _emailSender;

    public OrderService(IEmailSender emailSender) {
        _emailSender = emailSender; // injected, not created here
    }

    public void PlaceOrder(string customerEmail) {
        _emailSender.Send(customerEmail, "Order confirmed!");
    }
}

ASP.NET Core has a built-in DI container — registering IEmailSender once (builder.Services.AddScoped<IEmailSender, SmtpEmailSender>();) means every controller that asks for an IEmailSender in its constructor gets one automatically, with no manual wiring at each call site.

Common mistakes

  • A class calling new SmtpEmailSender() directly instead of depending on the IEmailSender interface — this makes it impossible to substitute a test double (a mock) in a unit test.