Skip to content

Add a resolve middleware example - #41

Merged
tillig merged 2 commits into
mainfrom
feature/middleware-example
Sep 1, 2026
Merged

Add a resolve middleware example#41
tillig merged 2 commits into
mainfrom
feature/middleware-example

Conversation

@tillig

@tillig tillig commented Sep 1, 2026

Copy link
Copy Markdown
Member

Part of #32, and the Examples half of autofac/Documentation#160.

Proposed Changes

MiddlewarePipelineExample, covering five things resolve middleware is actually good for. Each middleware is its own class; Program runs them in turn and prints what each one did.

Scenario Middleware Point
Every registration at once ActivationAuditMiddleware The autofac/Autofac#1337 request: a hook for all registered components, with no per-registration call
Timing TimingMiddleware Measure activation cost for a service
Short-circuit CachingMiddleware Set Instance, never call next, and activation is skipped
Ambient state CorrelationIdMiddleware ChangeParameters supplies a value no caller passed
Fail fast RootScopeGuardMiddleware Readable error when something is resolved from the root scope

autofac/Documentation#160 asked for real-world middleware examples because the only sample was the Hello World logging lambda. The documentation section that links to this lands in a separate Documentation PR.

The scenario worth reading twice

CorrelationIdMiddleware does not work the obvious way, and that is why it is in here. Parameter selection is a registration pipeline phase, so registering it with RegisterServiceMiddleware throws:

Cannot add registration middleware in phase 'ParameterSelection' to a service pipeline.
Valid registration middleware phases: [ResolveRequestStart, ScopeSelection, Decoration, Sharing, ServicePipelineEnd]

I hit that while writing this and kept it rather than quietly picking a phase that worked. It is attached with ConfigurePipeline instead, and both the code comment and the README say why — that error message is the clearest explanation of why Autofac has two pipelines instead of one, which is the part of the docs page people skim.

Verification

All 20 projects build with 0 errors and 0 warnings in Release, both gates pass, and the example was run rather than only compiled. Every scenario produces its intended output: two components audited without either registration naming the middleware, an 80ms resolve reported, a cache hit that skips activation, two different correlation IDs injected across two resolves without a caller passing either, and the root-scope resolve rejected while the child-scope resolve succeeds.

The validators from earlier PRs all still pass: 12 launch configurations for 12 launchable projects with nothing missing or orphaned, every src directory has a README, and all 99 markdown links resolve.

Closes the Examples half of autofac/Documentation#160, which asked for real world
middleware beyond the logging snippet already in the documentation. Five
scenarios, one class each: audit every registration, time a resolve, short
circuit from a cache, inject ambient state as a parameter, and reject a resolve
that came straight from the root scope.

The first of those is the Autofac#1337 request, which wanted a hook invoked for
every registered component instead of an extension method call on each
registration.

The correlation ID scenario earns its place by being the one that does not work
the obvious way. Parameter selection is a registration pipeline phase, so
registering it as service middleware throws with a message listing the phases a
service pipeline accepts. It is attached with ConfigurePipeline instead, and the
example says why, because that error is the clearest available explanation of
why there are two pipelines.

Part of #32
Comment thread src/MiddlewarePipelineExample/Program.cs
Every method in Program now carries a short summary of the problem its scenario
illustrates, so the file reads as a tour rather than five similar-looking blocks.

Also drops an unused Autofac.Core.Resolving.Pipeline using. Nothing flagged it,
because IDE0005 does not fire without GenerateDocumentationFile; I confirmed it
was dead by compiling without it.

Part of #32
@tillig
tillig merged commit 1f492b5 into main Sep 1, 2026
8 checks passed
@tillig
tillig deleted the feature/middleware-example branch September 1, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant