[Design Pattern] - Dependency Injection trong ASP.NET Core
Dependency Injection is an extremely common technique for loosening objects and the classes that depend on them. Sounds too confusing, right?
This post describes this technique and gives you an overview (hopefully an objective one) of DI
1. The problem
Imagine you want to drink a coke and there are no bottles left at home. You have to go out to Circle K, wander around the store looking for a bottle of coke, pay, and come home
- You could forget to pay
- You could fail to find any Circle K nearby
- You could fail to find any bottle of coke in the circle k
- You could grab a bottle of Chương Dương sarsi by mistake instead of coke
With Dependency Injection things go differently
You hand money to a kid whose job is buying soft drinks for the neighborhood. 5 minutes later they show up with your bottle of coke
Someone else in the same neighborhood has almost the same need, but they want to drink pepsi
Instead of also going to the store to buy pepsi themselves and hitting the same problems you hit, they also call that kid over, and 5 minutes later a chilled bottle of pepsi is in their hands. That kid is a Service, and you depend on that kid to have a soft drink
2. The benefits
Back to the example above: what do you gain from using the kid’s soft-drink-buying Service?
- You don’t have to care what the kid does to get you the drink
- You can ask for many different kinds of drink without knowing what they look like or where they’re sold
3. Back to code
Back in code, how do you implement DI?
3.1. Interface
public interface IDrinkBuyer { void BuyDrink(string name); }
When the drink-buying kid above grows old, they’ll want to pass the drink-buying job on to another kid, and so on. Every drink-buying kid in the neighborhood has one basic method, BuyDrink, taking one param: the name of the drink to buy. You play the role of the WebApplication and call this method to get a drink
3.2. Implementation
The manager of these drink-buying kids assigns each kid their task
- Kid A buys at Circle K
- Kid B buys at Vinmart
And they implement it like this
public class CircleKDrinkBuyer: IDrinkBuyer
{
public void BuyDrink(string name)
{
// Go to circle k
// Find the -name- drink
// Buy it and deliver
}
}
public class VinmartDrinkBuyer: IDrinkBuyer
{
public void BuyDrink(string name)
{
// Go to Vinmart
// Find the -name- drink
// Buy it and deliver
}
}
That’s it. When your house is near Vinmart, the manager posts kid B - VinmartDrinkBuyer - in front of your gate. Whenever you need to buy a drink, you call them. You have no idea that kid B only knows how to buy drinks at Vinmart. All you care about is that you call them and you get a drink
4. Register
So how do you declare it in your app? When you create a new asp.net core 2 app, there are already a few methods to get you started right away

by adding the line services.AddScoped(); you have declared that every class using the BuyDrink method will buy drinks at CircleK
4.1. Lifetime
AddScoped sets this service’s lifetime; there are 3 kinds:
- Transient: every call to it is a completely new instance. This only fits super lightweight services that hold no state
- Scoped: within one request it is created exactly once
- Singleton: it is created the first time it is called and lives on until your app dies
4.2. Contructor Injection
After registering your service with a suitable lifetime, the next thing is injecting it where it’s needed (usually a controller). ASP.NET Core 2 lets you inject a service into a controller through that controller’s constructor

4.3. Action Injection
Sometimes you only need this service in one specific action of the controller, and then the way is a bit different
public IActionResult About([FromServices] IDrinkBuyer drinkBuyer)
{
drinkBuyer.BuyDrink("coca");
return View();
}
4.4. A Service inside a Service
Nested services, child services, and so on and so on
Sometimes you need a child service for the parent service to run — so how do you inject it?
Very simple: constructor injection again
Say the DrinkBuyer Service needs the Trasport service to run
public interface ITransport
{
void Transport();
}
public class BikeTransport: ITransport
{
public void Transport()
{
// transport by bike
}
}
public class CarTransport: ITransport
{
public void Transport()
{
// transport by car
}
}
first register it in Startup.cs: services.AddScoped();
then you inject it into DrinkBuyer like this
public class CircleKDrinkBuyer: IDrinkBuyer
{
private readonly ITransport _transport;
public CircleKDrinkBuyer(ITransport transport)
{
_transport = transport;
}
public void BuyDrink(string name) {
// Go to circle k
// Find the -name- drink
// Buy it
// Deliver
_transport.Transport();
}
}
and that’s it :D