7. IoC and DI containers
Answer as submitted
“Yes — built-in .NET DI, Autofac/StructureMap-style containers and Spring's IoC container.”
Expanded answer
Yes. Microsoft.Extensions.DependencyInjection is my baseline container — interface-to-implementation bindings, explicit singleton/scoped/transient lifetimes, factory delegates for runtime parameters, decorators for cross-cutting behaviour and a composition root kept at the application boundary. I have also worked with Autofac-style modules (assembly scanning, keyed registrations, lifetime scopes, register-decorator) and legacy StructureMap-family containers in older codebases, plus Spring's IoC container on the Java track and FastAPI's Depends graph / NestJS providers on Python and Node services.
| Decision | Typical registration | Why it is done this way |
|---|---|---|
| Interface binding | AddScoped<IFoo, Foo>() | Callers depend on the abstraction, so implementations can be swapped. |
| Lifetimes | Singleton / Scoped / Transient | Instance reuse per application, per request, or per resolve. |
| Constructor injection | public Foo(IBar bar, ILogger<Foo> log) | Dependencies are explicit and testable; no service locator, no static state. |
| Decorators | Decorate<IFoo, CachedFoo>() | Caching, logging, retries and transactions stay out of the business class. |
| Factory delegates | AddTransient<Func<string, IExporter>>(...) | Runtime parameters are chosen by code, not resolved from the container. |
| Graph validation | ValidateOnBuild + ValidateScopes | Captive dependencies fail at start-up instead of in production. |
| Modules / scanning | Autofac Module, StructureMap registry | Feature registrations are grouped and packaged together. |
Live dependency-injection workflow proof
The running component below changes its registration/result view through real event binding. Select a step to see the registration or resolution call, the reasoning behind it, and the observable result from the container.
Choose a container step
Select a step to inspect the registration or resolution, the reasoning and the result the host produces.
$ services.AddScoped<IOrderService, OrderService>();
Maps an abstraction to an implementation with an explicit lifetime, so callers depend on the interface and never construct their collaborators.
3 registrations · scope: per request validateOnBuild: true · validateScopes: true
How the container is kept healthy
ValidateOnBuild plus ValidateScopes so a captive dependency is rejected before the first request. The payoff is infrastructure that can be swapped or faked in tests without touching business logic.
Source files
Select a file to inspect the proof with syntax highlighting and line numbers. The first file is the code running the component above; the other two are the production shapes of the same registrations.
Acceptance criteria
- Names the .NET container and the Autofac/StructureMap-style alternatives.
- Distinguishes registration, lifetime selection, resolution and validation.
- Shows an interactive proof of choosing a container step and reading its result.
- Defines lifetimes explicitly and rejects captive dependencies at start-up.
- Defers scope handling in background jobs, migrations and benchmarking to a later topic.