Dependency Injection Demystified in ASP.NET Core

Dependency Injection (DI) isn’t just a buzzword. It’s one of the reasons ASP.NET Core apps are clean, testable, and maintainable.

In this article, we’ll break down DI in the most practical way possible with code, real-world usage, and clarity.


🧠 What is Dependency Injection?

Dependency Injection is a design pattern where dependencies (services) are passed into a class rather than the class creating them itself.

Why?
Because it:

  • ✅ Reduces coupling
  • ✅ Increases testability
  • ✅ Improves code flexibility and reuse

🧰 DI in ASP.NET Core: Built-in by Default

ASP.NET Core comes with a built-in IoC (Inversion of Control) container. You register services in Program.cs:

builder.Services.AddScoped<IEmailSender, SmtpEmailSender>();

Then inject them into your classes:

public class AccountController : Controller
{
    private readonly IEmailSender _emailSender;

    public AccountController(IEmailSender emailSender)
    {
        _emailSender = emailSender;
    }
}

ASP.NET Core takes care of creating SmtpEmailSender and passing it in when needed.


🧩 Service Lifetimes

When registering services, choose a lifetime:

// A new instance every time
services.AddTransient<IMyService, MyService>();

// One instance per request
services.AddScoped<IMyService, MyService>();

// One instance for the entire app
services.AddSingleton<IMyService, MyService>();

Choose wisely — especially when dealing with databases or shared state.


💡 Real-world Use Case

Let’s say you want to send SMS via multiple providers (Twilio, Vonage, etc.). You can inject a strategy pattern like this:

public interface ISmsSender { void Send(string to, string message); }
public class TwilioSender : ISmsSender { ... }
public class TermiiSender : ISmsSender { ... }

Register based on config:

if (useTwilio)
    services.AddScoped<ISmsSender, TwilioSender>();
else
    services.AddScoped<ISmsSender, TermiiSender>();

Then inject and call it without knowing which one you got!


🔄 Injecting Configuration

Need to inject app settings?

builder.Services.Configure<MyAppSettings>(
    builder.Configuration.GetSection("MyAppSettings"));

And in your service:

public MyService(IOptions<MyAppSettings> options)
{
    var config = options.Value;
}

🧪 Testability Bonus

DI makes unit testing easy. Just pass in mock dependencies during testing — no hardcoded logic!


✅ Up Next

With DI under your belt, you’re ready to build real APIs with controllers, model validation, and solid error handling.

➡️ Building RESTful APIs the Right Way →

Let’s keep building clean, powerful ASP.NET Core apps 👊

0
Subscribe to my newsletter

Read articles from Esanju Babatunde directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Esanju Babatunde
Esanju Babatunde