RTS questionnaire · Q07 · Dependency-injection proof

Have you worked with IoC/DI containers such as Autofac, StructureMap, or similar frameworks?

A runnable review of the inversion-of-control decisions behind the answer: how the graph is registered, which lifetime each service gets, and how configuration errors are caught at start-up.

Status: reviewed Live DI workflow .NET DI · Autofac · Spring Jump to live proof ↓

7. IoC and DI containers

Answer as submitted

“Yes — built-in .NET DI, Autofac/StructureMap-style containers and Spring's IoC container.”
Technical decision: expand. The submitted line names the containers but not the discipline that makes them useful. This page is the separate, detailed version: it shows the registrations, the lifetimes, the decorators and the start-up validation that keeps the graph healthy.

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.

DecisionTypical registrationWhy it is done this way
Interface bindingAddScoped<IFoo, Foo>()Callers depend on the abstraction, so implementations can be swapped.
LifetimesSingleton / Scoped / TransientInstance reuse per application, per request, or per resolve.
Constructor injectionpublic Foo(IBar bar, ILogger<Foo> log)Dependencies are explicit and testable; no service locator, no static state.
DecoratorsDecorate<IFoo, CachedFoo>()Caching, logging, retries and transactions stay out of the business class.
Factory delegatesAddTransient<Func<string, IExporter>>(...)Runtime parameters are chosen by code, not resolved from the container.
Graph validationValidateOnBuild + ValidateScopesCaptive dependencies fail at start-up instead of in production.
Modules / scanningAutofac Module, StructureMap registryFeature 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.

LIVE PREVIEW
RUNNING
DI WORKFLOWRUNNING

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

Rules I apply. A composition root at the application boundary and nowhere else, one explicit lifetime per registration, constructor injection instead of a service locator, decorators for everything cross-cutting, and 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.
Boundary for Q07: this page covers containers, lifetimes and registration patterns. Per-request scope management inside background jobs, third-party container migration strategy and container-performance benchmarking are separate topics.

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