Lesson 15 / 26
Dependency Injection Basics
Register an interface and its implementation and receive it in an endpoint.
Ask, do not create
Instead of writing new EmailSender() inside your code, you ask for an IEmailSender and the built-in container gives you one. This makes code easy to test because tests can pass a fake.
Register, resolve, use
You register services once at startup, and the container supplies them wherever they are requested.
Register and inject
AddScoped registers the pair. The endpoint parameter of type IGreeter is injected automatically.
builder.Services.AddScoped<IGreeter, Greeter>();
var app = builder.Build();
app.MapGet("/hi/{name}", (string name, IGreeter g) => g.Greet(name));
app.Run();
public interface IGreeter { string Greet(string name); }
public class Greeter : IGreeter
{
public string Greet(string name) => $"Hello, {name}!";
}The canteen counter
You do not cook your own lunch; you tell the counter what you need. If the canteen changes its chef, you do not care. Interfaces play the same role between your code and its helpers.
Quick check: Why depend on an interface instead of a concrete class?
- Interfaces are faster at runtime
- It lets you swap implementations, such as a fake in tests
- The compiler requires it
- It removes the need for a container
Answer
It lets you swap implementations, such as a fake in tests — Depending on an abstraction lets you replace the implementation without changing the caller.