Dependency Injection in C#: A Complete Guide
Reviewed & published by Brayan K
Master Dependency Injection in C# and ASP.NET Core — DI patterns, service lifetimes, interfaces and containers.
Learn what DI is, why it matters, and how to implement it in modern C# applications.
Introduction
Dependency Injection (DI) is one of the most important concepts in modern C# development. If you're using ASP.NET Core, Unity game engine, MAUI, Blazor, or even WPF — DI is everywhere.
This article will help you understand:
- What dependency injection is
- Why it makes your applications cleaner and easier to maintain
- Common DI patterns
- DI containers in C#
- Real-world examples
- How DI works inside ASP.NET Core
Let's break it down in a simple, beginner-friendly way.
1. What Is Dependency Injection?
To understand DI, first understand the concept of dependency.
A Dependency = Something a class needs to function.
class EmailService
{
public void Send(string message) {}
}
class UserController
{
private readonly EmailService _emailService;
public UserController()
{
_emailService = new EmailService();
}
}- UserController depends on EmailService.
- The controller creates its own dependency.
Dependency Injection fixes this.
Instead of creating the dependency inside the class…
You inject the dependency from outside:
class UserController
{
private readonly IEmailService _emailService;
public UserController(IEmailService emailService)
{
_emailService = emailService;
}
}Now the class is:
2. Why Use Dependency Injection?
1. Makes Testing Easy
You can inject fake or mock objects:
var fakeEmail = new FakeEmailService();
var controller = new UserController(fakeEmail);2. Promotes Loose Coupling
Your class no longer chooses its own dependencies — they are given to it.
3. Improves Code Reusability
Classes are more modular.
4. Standard in ASP.NET Core
Every controller, middleware, and service uses DI by default.
5. Follows SOLID Principles
Mainly OCP (Open/Closed) and DIP (Dependency Inversion Principle).
3. Constructor Injection (Most Common)
public class PaymentController
{
private readonly IPaymentProcessor _processor;
public PaymentController(IPaymentProcessor processor)
{
_processor = processor;
}
public void Pay() => _processor.Process();
}This is the preferred method in most C# applications.
4. Method Injection
void ProcessOrder(IEmailService emailService)
{
emailService.Send("Order confirmed");
}Useful for rarely-used dependencies.
5. Property Injection
public ICacheService CacheService { get; set; }Less common, used in frameworks where setter injection is needed.
6. Using Dependency Injection in ASP.NET Core
ASP.NET Core has a powerful built-in DI system.
You register services in Program.cs:
builder.Services.AddTransient<IEmailService, EmailService>();
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddSingleton<ILogger, Logger>();| Lifetime | Meaning | Example Use |
|---|---|---|
| Transient | New instance each time | Lightweight services |
| Scoped | One instance per HTTP request | Repository classes |
| Singleton | One instance for whole app | Logging, caching |
public class AuthController : ControllerBase
{
private readonly IUserRepository _repo;
public AuthController(IUserRepository repo)
{
_repo = repo;
}
}public async Task Invoke(HttpContext context, ILogger logger)@inject IEmailService EmailService7. DI Using Interfaces (Best Practice)
Always inject interfaces, not concrete classes.
public UserController(EmailService service)public UserController(IEmailService service)- Easy to mock
- Easy to replace implementations
- Cleaner architecture
8. DI Containers Available in C#
ASP.NET Core includes a built-in DI container, but other popular ones include:
Easy to use, slower performance.
Used heavily in game engine Unity.
Most modern apps stick with the built-in DI system unless advanced features are needed.
9. Real-World Example: Logging System
public interface ILoggerService
{
void Log(string message);
}public class FileLogger : ILoggerService
{
public void Log(string message) =>
File.AppendAllText("log.txt", message);
}Use in your class:
public class OrderService
{
private readonly ILoggerService _logger;
public OrderService(ILoggerService logger)
{
_logger = logger;
}
public void CreateOrder()
{
_logger.Log("Order created");
}
}builder.Services.AddSingleton<ILoggerService, FileLogger>();10. Summary
Dependency Injection is essential for clean and scalable C# architecture.
- Why DI makes code easier to maintain and test
- Constructor, property, and method injection
- Service registration (Transient, Scoped, Singleton)
- Interfaces vs concrete classes
- Real examples + ASP.NET Core DI
If you're building any modern C# project — from APIs to games — DI will be one of your most-used patterns.
Related articles
- C# LINQ: A Complete Guide — Explore the power of Language Integrated Query and transform how you work with data in C#.