Repository navigation
Unkeyed decoration regresses providers without a keyed availability probe #120
Description
Activity
Implemented in draft PR #123: #123
This was prioritized as the new regression among the open bug/P2 reports. The exact issue reproduction independently confirms that develop fails after decoration on net472/net8.0/net9.0/net10.0 while published 0.8.0 succeeds on every target. The fixed source now succeeds on every target too.
The original-type activator previously requested IServiceProviderIsKeyedService before examining any constructor. It now acquires that probe only when a constructor dependency needs a non-null lookup key. Parameterless and ordinary-dependency originals, null owner contexts, and direct ServiceKey injection therefore retain ordinary provider support. Private decorator slots still use keyed resolution; availability probing and keyed resolution remain separate capabilities. Actual explicit/inherited-key dependencies still fail clearly when the keyed availability probe is missing. Nonempty DependsOn maps retain their existing requirements.
Preserving #111's generic-constraint checks required the existing snapshot helper/cache to accept the ordinary probe interface as well. For native DI, both interfaces refer to the same CallSiteFactory descriptor owner. The helper keeps its exact native-type guard, copied descriptor field, metadata-shape guard, weak provider-specific cache, and preference for Mammoth's snapshot. There is no additional reflection lookup or dependency activation during planning. The rationale is documented in the architecture document, already linked from the code comment and README Architecture section.
Tests were committed first: 75 failed and 6 keyed controls passed on each target. All 81 new cases now pass, including wrappers whose ordinary probe implements only IServiceProviderIsService, native/snapshot/diagnostic providers, repeated layers, lifetimes/disposal, constructor policies, constraint failures, and keyed controls.
Verification for final commit
7cb718572fa423b050c6083ae554f66064d35cb6:- Local Windows restore and Release CI-style build passed.
- Local and Windows CI suites each passed 2,578 tests on all four targets: 10,312 passed, zero failed/skipped per run. net472 executed under .NET Framework 4.8.9345.0.
- Local and CI native DI 10.0.0 cache probes passed on all four targets: 100 interleaved enumerations each after observed native compilation.
- Whitespace check passed. No applicable checks were unavailable.
- Only the two existing net472 support warnings from Microsoft.Extensions.Telemetry.Abstractions and Microsoft.Extensions.Diagnostics.Testing 10.0.0 remain; no compiler/analyzer warnings or errors.
- Exact-commit CI succeeded. Pack and Publish were skipped.
Paused for review before another issue. #121 and #122 remain separate open defects; resolve and review those before completing the release-validation checkpoint. No release actions were taken.
Problem
Priority: P2 · Type: bug · New regression versus published 0.8.0.
Adding an unkeyed forwarding decorator now requires
IServiceProviderIsKeyedService, even when the original implementation has a parameterless constructor. A provider/wrapper that supports ordinary availability probing and keyed resolution, but does not expose the keyed availability probe, succeeds before decoration and with published Mammoth 0.8.0; the current decorated registration throws.The reproduction models that provider by passing a wrapper to registration factories. It preserves
IServiceProviderIsServiceandIKeyedServiceProvider, including resolution of Mammoth's private decoration slots; onlyIServiceProviderIsKeyedServiceis unavailable. The ordinary native BuildServiceProvider control itself continues to expose all its normal probes.The #111 fix routes original decorated implementation types through NativeConstructorActivator, which unconditionally requires both probes. The new keyed-probe requirement applies before examining whether any constructor actually uses a keyed dependency.
Reproduction
Save the following files under
artifacts/release-review-20261009/issue-probes/keyed-probe/in the reviewed checkout. Build with a .NET 10 SDK.repro.csproj:Program.cs:Run
dotnet run --project artifacts/release-review-20261009/issue-probes/keyed-probe/repro.csproj -c Release -f net472; repeat fornet8.0,net9.0andnet10.0. Add-p:PublishedBaseline=trueto run the published 0.8.0 control.Observed versus expected
Expected: ordinary unkeyed decoration retains its previous provider capability requirements while preserving the corrected native constructor rules. No keyed availability check is necessary for this parameterless original.
Fix direction and regression coverage
Require the keyed availability probe only when keyed lookup/planning actually needs it, with an appropriate path for ordinary activation. Preserve the #111 constructor-selection fixes and the existing mapped/keyed provider contracts. Cover parameterless and ordinary-dependency originals, provider wrappers lacking the keyed probe, repeated decorators and disposal; retain explicit-key and inherited-key controls.
Verification and related work
Executed against develop commit b531864 with Microsoft.Extensions.DependencyInjection 10.0.0, on Windows net472 (.NET Framework 4.8.9345.0), .NET 8.0.31, .NET 9.0.20 and .NET 10.0.12. Published Mammoth 0.8.0 was compared on the same targets and DI dependency. These are standalone executable comparison probes; production source was not modified.
Related: closed #111. This new report isolates the additional provider-capability requirement introduced in original decorator activation.
Prepared with OpenAI Codex.