You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I just shipped updated versions across all the Autofac libraries, and this repo has fallen behind far enough that several examples no longer reflect what we actually publish. This issue tracks getting it current, gating it so it stays current, and closing the biggest coverage gaps.
Why this is more than a version bump
Three findings from the audit shape the work:
The .NET Framework integration packages target net481 now. Confirmed at the release tags — Autofac.Mvc5 v7.0.0, Autofac.Wcf v8.0.0, Autofac.Web v8.0.0, Autofac.Owin v8.0.0. The six net472 projects in here cannot take current packages without retargeting. They are also the furthest behind: still on Autofac 6.5.0 against a current 9.3.2.
Four org repos have no published package, so they can't have copy-pasteable examples: Autofac.Analyzers, Autofac.AspNetCore, Autofac.Extensions.Hosting, Autofac.Extras.AggregateService.SourceGenerator. Notably that rules out using our own analyzer package to raise code quality in here.
dotnet format fails today — missing UTF-8 BOM in the three ASP.NET Core projects, import ordering, final newlines, and one whitespace error. All auto-fixable, but it means adding the CI gate and fixing the code have to land together.
Two bugs also turned up that have nothing to do with modernization:
WebFormsExample.csproj sets RootNamespace and AssemblyName to MvcExample. Combined with OutputPath=bin/ and AppendTargetFrameworkToOutputPath=false, its output collides with the real MvcExample.
ci.yml triggers on develop and gates pull requests against develop, but this repo only has main — it's one of our non-Gitflow repos. PR builds never fire.
Decisions
Recording these so the tasks below don't get relitigated:
Retarget the legacy examples to net481 rather than freezing them on Autofac 6.x. Examples that don't match what we ship are worse than no examples.
Keep CI local to this repo. The org's shared ci.yml assumes default.proj, a codecov upload, and NuGet publishing — none of which apply to a repo with no packages and no tests. Adding inputs for a single consumer isn't worth the conditional complexity.
.editorconfig plus AnalysisLevel=latest-recommended, and no StyleCop. Nullable on, warnings-as-errors in Release. StyleCop wants file headers and XML docs on public members, which is a lot of ceremony wrapped around ten-line teaching samples.
No test projects except where testing is the point. The Moq and FakeItEasy examples are the only ones that should carry tests, and both are deferred below.
Work
Ordered, because they stack. Each lands as its own pull request against main.
1. Root config refresh. Replace .editorconfig with the current one from the core repo (ours is the pre-2020 version — no per-filetype sections, no dotnet_diagnostic severities). Add .markdownlint.json; pre-commit runs markdownlint with no config today. Bump the markdownlint hook to v0.49.1 to match core. Relax the global.json pin from 10.0.203 to 10.0.100 so any 10.0 SDK can build this. Fix the develop triggers in ci.yml. Clean up the README: dead AppVeyor badge, Examples.sln should be Examples.slnx, and it still advertises a ServiceFabric example that was deleted in cae30c6. Verify:pre-commit run --all-files is clean.
2. CI gates. Add dotnet format and pre-commit jobs to build.yml, mirroring the org workflow's job bodies minus the default.proj, codecov, and publish steps. The format job needs windows-latest — net481 projects won't restore on Linux. Also port the org workflow's gate job: Refresh root configuration and normalize the repo #33 built twice for one commit, once for the branch push and once for the pull request, and adding two more jobs would triple that waste. Verify: all jobs run, fail loudly on a deliberate violation, and only one run happens per change.
3. Dependency updates, net10.0 projects. Autofac and the integration packages to current, plus Microsoft.Extensions.*. Split from the retarget below so a net481 surprise can't block the modern examples. Verify:dotnet build Examples.slnx -c Release clean.
4. Retarget net472 → net481. All six legacy projects, with every Autofac package to current, plus Microsoft.AspNet.Mvc, Newtonsoft.Json, Microsoft.Bcl.AsyncInterfaces, and Microsoft.NETFramework.ReferenceAssemblies. Verify:dotnet build Examples.slnx -c Release clean on Windows.
5. Code standards pass. Add a root Directory.Build.props — there is none today — carrying Nullable, ImplicitUsings, EnforceCodeStyleInBuild, AnalysisLevel, and TreatWarningsAsErrors in Release, so policy lives in one place instead of fifteen csproj files. Then fix the fallout: file-scoped namespaces everywhere (ccd9b35 claimed to do this but GenericHostBuilderExample, AttributeMetadataExample, and the net472 projects still use block scope), drop usings made redundant by ImplicitUsings, remove the one remaining // ReSharper comment, normalize the stray csproj blank lines, and fix the WebFormsExample assembly name bug. Applied as a scripted pass over the project list so the diffs are identical by construction. Verify: zero warnings in Release, dotnet format --verify-no-changes clean.
6. VS Code integration.launch.json still has configurations for AspNetCore3Example and AspNetCore3ChildLifetimeScope, neither of which exists anymore, and every surviving one points at a bin/Debug/net6.0/ path for a project that targets net10.0. AspNetCoreChildLifetimeScope and AspNetCoreNoStartupExample do exist and have no configuration at all. Environment variables move out of launch.json and into the per-project launchSettings.json — all eight web projects already have one — referenced from the launch configuration via launchSettingsProfile so there's a single place to set them. Switch to DOTNET_ENVIRONMENT; the ASPNETCORE_-prefixed form is the older pattern. Only the three ASP.NET Core projects actually matter there, since classic ASP.NET reads neither prefix and the .NET Framework entries are inert. settings.json still carries omnisharp.* keys the Roslyn language server ignores, and extensions.json recommends a test explorer for a repo with no tests. Depends on item 4, because the launch paths embed target frameworks. Verify: every configuration in launch.json starts the project it names.
7. Navigation. A table in the README — example, what it demonstrates, packages, link to the matching docs page. A short README per example: what it shows, how to run it, link to the doc page, and nothing else. Group Examples.slnx into solution folders by area instead of one flat /src/. Leaving the src/ layout alone; restructuring it churns every inbound docs link for no gain once the table exists. Verify: every src/ directory has a README.
8. New examples. DynamicProxy interception, Autofac.Pooling, Autofac.Diagnostics.DotGraph, Autofac.AspNetCore.Multitenant, and a middleware example for More middleware examples Documentation#160. All net10.0, all cross-platform. Verify: each builds and runs.
9. Documentation repo follow-up. All ten cross-links into this repo point at /tree/master/... and our default branch is main — GitHub's rename redirect isn't something to rely on. Same pull request adds the middleware section that closes More middleware examples Documentation#160 and links the four new examples from their doc pages.
advanced/pipelines.rst covers the mechanics thoroughly, but its only sample is the Hello World logging lambda, and that issue asks for concrete real-world cases. Scenarios to cover, in priority order:
Blanket AOP across every registration — the Hook/Extension point modifying IRegistrationBuilder Autofac#1337 case that issue cites. Wrapping every resolved service via the Registered event or IServiceMiddlewareSource, with no per-registration extension call. This is the one that wasn't obvious, so it's the point.
Resolve timing and instrumentation — measuring activation cost per service.
Short-circuiting — returning a cached instance without calling next.
Ambient parameter injection — pushing a correlation ID or tenant into every activation through ResolveRequestContext.
Fail-fast scope validation — service middleware that throws something readable when a service is resolved from the wrong scope.
Coverage gaps deferred
The goal is one example per non-deprecated library. After item 8, these are still uncovered:
Package
Disposition
Autofac.Extras.Moq
Worth doing. xUnit test project — one of the two places tests belong here.
Autofac.Extras.FakeItEasy
Worth doing, same shape as Moq.
Autofac.Extras.AggregateService
Worth doing. Small console app.
Autofac.Mef
Worth doing. Small console app.
Autofac.Mvc5.Owin
Low value, and better as an addition to the existing OWIN self-host example than a new project.
Autofac.SignalR2
Low value. net481, ASP.NET SignalR 2. Legacy, but it is a shipping package.
Autofac.Extras.CommonServiceLocator
Not planning to cover. CSL upstream is abandoned; not formally deprecated, but not worth teaching.
Autofac.ServiceFabric
Not planning to cover. Deliberately deleted in cae30c6; the SF SDK is Windows-only and isn't on GitHub runners, so any example we add here will rot. The tagged history still has the old one.
Blocked. Unpublished, so an example wouldn't be runnable by anyone reading it.
Separately, there are documented core features with no example anywhere — decorators and composites, keyed services, registration sources, delegate factories, owned instances, native AOT and trimming — and integration/blazor.rst and integration/azurefunctions.rst have docs with no example. That's a real gap against "one example per documented feature," but it's much larger in scope than one-per-library and belongs in its own issue.
I just shipped updated versions across all the Autofac libraries, and this repo has fallen behind far enough that several examples no longer reflect what we actually publish. This issue tracks getting it current, gating it so it stays current, and closing the biggest coverage gaps.
Why this is more than a version bump
Three findings from the audit shape the work:
The .NET Framework integration packages target
net481now. Confirmed at the release tags —Autofac.Mvc5v7.0.0,Autofac.Wcfv8.0.0,Autofac.Webv8.0.0,Autofac.Owinv8.0.0. The sixnet472projects in here cannot take current packages without retargeting. They are also the furthest behind: still onAutofac 6.5.0against a current 9.3.2.Four org repos have no published package, so they can't have copy-pasteable examples:
Autofac.Analyzers,Autofac.AspNetCore,Autofac.Extensions.Hosting,Autofac.Extras.AggregateService.SourceGenerator. Notably that rules out using our own analyzer package to raise code quality in here.dotnet formatfails today — missing UTF-8 BOM in the three ASP.NET Core projects, import ordering, final newlines, and one whitespace error. All auto-fixable, but it means adding the CI gate and fixing the code have to land together.Two bugs also turned up that have nothing to do with modernization:
WebFormsExample.csprojsetsRootNamespaceandAssemblyNametoMvcExample. Combined withOutputPath=bin/andAppendTargetFrameworkToOutputPath=false, its output collides with the real MvcExample.ci.ymltriggers ondevelopand gates pull requests againstdevelop, but this repo only hasmain— it's one of our non-Gitflow repos. PR builds never fire.Decisions
Recording these so the tasks below don't get relitigated:
net481rather than freezing them on Autofac 6.x. Examples that don't match what we ship are worse than no examples.ci.ymlassumesdefault.proj, a codecov upload, and NuGet publishing — none of which apply to a repo with no packages and no tests. Adding inputs for a single consumer isn't worth the conditional complexity..editorconfigplusAnalysisLevel=latest-recommended, and no StyleCop. Nullable on, warnings-as-errors in Release. StyleCop wants file headers and XML docs on public members, which is a lot of ceremony wrapped around ten-line teaching samples.Work
Ordered, because they stack. Each lands as its own pull request against
main..editorconfigwith the current one from the core repo (ours is the pre-2020 version — no per-filetype sections, nodotnet_diagnosticseverities). Add.markdownlint.json; pre-commit runs markdownlint with no config today. Bump the markdownlint hook to v0.49.1 to match core. Relax theglobal.jsonpin from10.0.203to10.0.100so any 10.0 SDK can build this. Fix thedeveloptriggers inci.yml. Clean up the README: dead AppVeyor badge,Examples.slnshould beExamples.slnx, and it still advertises a ServiceFabric example that was deleted in cae30c6. Verify:pre-commit run --all-filesis clean.dotnet formatandpre-commitjobs tobuild.yml, mirroring the org workflow's job bodies minus thedefault.proj, codecov, and publish steps. The format job needswindows-latest—net481projects won't restore on Linux. Also port the org workflow'sgatejob: Refresh root configuration and normalize the repo #33 built twice for one commit, once for the branch push and once for the pull request, and adding two more jobs would triple that waste. Verify: all jobs run, fail loudly on a deliberate violation, and only one run happens per change.net10.0projects. Autofac and the integration packages to current, plusMicrosoft.Extensions.*. Split from the retarget below so anet481surprise can't block the modern examples. Verify:dotnet build Examples.slnx -c Releaseclean.net472→net481. All six legacy projects, with every Autofac package to current, plusMicrosoft.AspNet.Mvc,Newtonsoft.Json,Microsoft.Bcl.AsyncInterfaces, andMicrosoft.NETFramework.ReferenceAssemblies. Verify:dotnet build Examples.slnx -c Releaseclean on Windows.Directory.Build.props— there is none today — carryingNullable,ImplicitUsings,EnforceCodeStyleInBuild,AnalysisLevel, andTreatWarningsAsErrorsin Release, so policy lives in one place instead of fifteen csproj files. Then fix the fallout: file-scoped namespaces everywhere (ccd9b35 claimed to do this but GenericHostBuilderExample, AttributeMetadataExample, and thenet472projects still use block scope), drop usings made redundant byImplicitUsings, remove the one remaining// ReSharpercomment, normalize the stray csproj blank lines, and fix the WebFormsExample assembly name bug. Applied as a scripted pass over the project list so the diffs are identical by construction. Verify: zero warnings in Release,dotnet format --verify-no-changesclean.launch.jsonstill has configurations forAspNetCore3ExampleandAspNetCore3ChildLifetimeScope, neither of which exists anymore, and every surviving one points at abin/Debug/net6.0/path for a project that targetsnet10.0. AspNetCoreChildLifetimeScope and AspNetCoreNoStartupExample do exist and have no configuration at all. Environment variables move out oflaunch.jsonand into the per-projectlaunchSettings.json— all eight web projects already have one — referenced from the launch configuration vialaunchSettingsProfileso there's a single place to set them. Switch toDOTNET_ENVIRONMENT; theASPNETCORE_-prefixed form is the older pattern. Only the three ASP.NET Core projects actually matter there, since classic ASP.NET reads neither prefix and the .NET Framework entries are inert.settings.jsonstill carriesomnisharp.*keys the Roslyn language server ignores, andextensions.jsonrecommends a test explorer for a repo with no tests. Depends on item 4, because the launch paths embed target frameworks. Verify: every configuration inlaunch.jsonstarts the project it names.Examples.slnxinto solution folders by area instead of one flat/src/. Leaving thesrc/layout alone; restructuring it churns every inbound docs link for no gain once the table exists. Verify: everysrc/directory has a README.net10.0, all cross-platform. Verify: each builds and runs./tree/master/...and our default branch ismain— GitHub's rename redirect isn't something to rely on. Same pull request adds the middleware section that closes More middleware examples Documentation#160 and links the four new examples from their doc pages.Middleware examples for autofac/Documentation#160
advanced/pipelines.rstcovers the mechanics thoroughly, but its only sample is the Hello World logging lambda, and that issue asks for concrete real-world cases. Scenarios to cover, in priority order:Registeredevent orIServiceMiddlewareSource, with no per-registration extension call. This is the one that wasn't obvious, so it's the point.next.ResolveRequestContext.Coverage gaps deferred
The goal is one example per non-deprecated library. After item 8, these are still uncovered:
Autofac.Extras.MoqAutofac.Extras.FakeItEasyAutofac.Extras.AggregateServiceAutofac.MefAutofac.Mvc5.OwinAutofac.SignalR2net481, ASP.NET SignalR 2. Legacy, but it is a shipping package.Autofac.Extras.CommonServiceLocatorAutofac.ServiceFabricAutofac.Analyzers,Autofac.AspNetCore,Autofac.Extensions.Hosting,Autofac.Extras.AggregateService.SourceGeneratorSeparately, there are documented core features with no example anywhere — decorators and composites, keyed services, registration sources, delegate factories, owned instances, native AOT and trimming — and
integration/blazor.rstandintegration/azurefunctions.rsthave docs with no example. That's a real gap against "one example per documented feature," but it's much larger in scope than one-per-library and belongs in its own issue.