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 👊
Subscribe to my newsletter
Read articles from Esanju Babatunde directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
