In lesson 2.10.4, you put a service’s dependencies into its constructor and composed everything in Program.cs with new. The lesson
ended with a preview: in a web application, you write the parts into a list, and ASP.NET Core creates the objects itself. That list, and
what works through it, is called dependency injection (DI): handing dependencies in from the outside.
You already used DI in the last lesson without calling it that: builder.Services.AddSingleton<IKladdeStore>(…) registered the store,
and every handler with a parameter IKladdeStore store got it. In this lesson, you learn what happens there, how long a created object
lives and which mistake can come out of that, one that shows up late in production and is hard to find then. At the end, the Kladde
registers the store and the clock and has a second endpoint that needs the clock.
The container
A web server creates objects for every request: handlers need a store, a clock, later a database connection and a client for mail. Who creates them, and when? In ASP.NET Core, that is the container (also called the service provider). It works in two steps:
- Register. Before
builder.Build(), you enter intobuilder.Serviceswhich services exist: which class applies to which type and how long an object of it should live.AddSingleton<IKladdeStore>(…)is such an entry. - Resolve. When someone needs a service, they ask the container for it. The container creates the object, and if its constructor has parameters of its own, it creates those too, step by step to the end of the chain.
It is asked in three places:
- As a parameter of a handler. If the type of a parameter is registered as a service, it comes from the container. You know this from
lesson 2.3.2, binding rule 4. With
[FromServices]before the parameter, you say it explicitly. - In the constructor of a class that itself comes from the container. That is how a service gets its dependencies without writing
new. - By hand through
GetRequiredService<T>(). You rarely need this, for example when an app starts. In the middle of logic, this pattern is called a “service locator” and hides what a class needs. Microsoft advises against it; use the constructor.
The container is no magic: it does what you did by hand in Program.cs in lesson 2.10.4. It only saves you from writing down the order,
and decides, according to what you specify, when an object is created new and when an existing one is reused.