Dependency Injection in C#: A Complete Guide
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.
Example:
Code Editor
Output
Here:
- UserController depends on EmailService.
- The controller creates its own dependency.
This causes problems:
Dependency Injection fixes this.
Instead of creating the dependency inside the class…
You inject the dependency from outside:
Code Editor
Output
Now the class is:
2. Why Use Dependency Injection?
1. Makes Testing Easy
You can inject fake or mock objects:
Code Editor
Output
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)
Code Editor
Output
This is the preferred method in most C# applications.
4. Method Injection
Code Editor
Output
Useful for rarely-used dependencies.
5. Property Injection
Code Editor
Output
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:
Code Editor
Output
Understanding Lifetimes
| 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 |
Injecting Services
In a controller:
Code Editor
Output
In middleware:
Code Editor
Output
In Razor pages:
Code Editor
Output
7. DI Using Interfaces (Best Practice)
Always inject interfaces, not concrete classes.
❌ Bad:
Code Editor
Output
✔ Good:
Code Editor
Output
Benefits:
- 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:
Autofac
Most powerful, feature-rich.
Ninject
Easy to use, slower performance.
Unity
Used heavily in game engine Unity.
LightInject
Fast and lightweight.
SimpleInjector
Great performance.
Most modern apps stick with the built-in DI system unless advanced features are needed.
9. Real-World Example: Logging System
Define the interface:
Code Editor
Output
Implement the service:
Code Editor
Output
Use in your class:
Code Editor
Output
Register service:
Code Editor
Output
10. Summary
Dependency Injection is essential for clean and scalable C# architecture.
You now understand:
- What DI is
- 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.