Skip to content

Fix keyed decorator inner dependency binding (#109) - #116

Merged
AGiorgetti merged 3 commits into
developfrom
codex/fix-109-decorator-binding
Oct 8, 2026
Merged

AGiorgetti merged 3 commits into
developfrom
codex/fix-109-decorator-binding

Conversation

@AGiorgetti

@AGiorgetti AGiorgetti commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Keyed decorator activation previously assigned the supplied inner instance to the first assignable constructor parameter, including an earlier [FromKeyedServices] dependency. For Wrapper([FromKeyedServices("other")] IWork other, IWork inner, [ServiceKey] object key), this could reject a valid constructor or silently swap the two services. Moving inner first happened to work.

The activator now reserves ServiceKey and FromKeyedServices parameters for their own context/lookup and binds the inner only to an ordinary assignable parameter. This preserves explicit, inherited and null-key lookup regardless of argument order, including object-typed dependencies, repeated layers, optional defaults and rejected constructors. The production change is one extra metadata check with an explanatory comment. Changelog updated under vNext Bug Fixes.

Verification:

  • Started from current develop 3b158fa92b2a2ba628d4e5133ebb5c62165aa6c0 in isolated branch/worktree codex/fix-109-decorator-binding; checked the issue, comments/timeline, existing PRs, branches and prior Preserve ServiceKey and inherited-key constructor semantics in custom activation paths #51 fix before changes.
  • Regression tests added in 508bbe6; two auxiliary registration-order fixtures corrected in ec100d8, before the implementation commit. Corrected tests against unchanged production code: 93 failed / 84 passed / 0 skipped per target on net472/net8.0/net9.0/net10.0.
  • Final commit: e5a2ca47bd0554a5b6da000216651b0bc144c1da.
  • Release restore/build with ContinuousIntegrationBuild=True: passed for all library compile targets (netstandard2.0/net8.0/net9.0/net10.0) and test targets.
  • Full Windows suite: 1,864 passed / 0 failed / 0 skipped per target on net472/net8.0/net9.0/net10.0 (7,456 total). The 177 new cases cover both parameter orders, interface/object dependencies, explicit/inherited/null keys, native/snapshot/diagnostic providers, type/factory/caller-owned instance registrations, all native lifetimes, two decorator layers, per-scope reuse, exactly-once owned disposal and caller-owned retention. Independent native controls verify original implementation/key and dependency identities. Missing/no-inner rejection tests check that dependency factories are not activated; optional dependencies retain their default.
  • Native DI 10.0.0 hot-cache probes: passed on all four targets, 100 interleaved enumerations each after observed native compilation.
  • git -c core.whitespace=cr-at-eol diff --check: passed.
  • Only the two existing net472 support warnings remain for Microsoft.Extensions.Telemetry.Abstractions and Microsoft.Extensions.Diagnostics.Testing 10.0.0; no new compiler/analyzer warnings.
  • GitHub Actions run 37790547876 succeeded for the exact final commit: 1,864 tests per target and all four native-cache probes passed. Pack and Publish were skipped. No final checks failed or were blocked.

Fixes #109

Co-authored-by: Codex codex@openai.com

Copy link
Copy Markdown
Contributor Author

Implemented #109 in draft PR #116, final commit e5a2ca47bd0554a5b6da000216651b0bc144c1da.

The decorator activator previously bound the supplied inner service to the first assignable parameter, even when that parameter had FromKeyedServices. An earlier same-interface or object-typed keyed dependency could therefore consume the inner instance, causing constructor rejection or silently swapped identities. The fix excludes those attributed parameters from inner binding, retaining the existing ServiceKey exclusion. The ordinary parameter receives the inner; explicit, inherited and null-key dependencies retain their own lookup, and optional defaults remain available.

The production fix is one additional cached-metadata check with an explanatory code comment; the changelog is updated under vNext Bug Fixes.

Verification:

  • Corrected regression tests were committed before production changes (508bbe6, ec100d8): 93 failed / 84 passed per target on unchanged production code.
  • Final Release restore/build passed across library targets netstandard2.0/net8.0/net9.0/net10.0.
  • Full Windows suite: 1,864 passed / 0 failed / 0 skipped on each of net472/net8.0/net9.0/net10.0 (7,456 total). The 177 new cases cover both parameter orders, explicit/inherited/null keys, interface/object parameters, native/snapshot/diagnostic providers, type/factory/caller-owned registrations, every lifetime, repeated layers, reference identities, scope reuse, disposal ownership, optional defaults and rejected constructors without dependency-factory activation. Native controls verify expected implementation/key and dependency identities.
  • Native DI 10.0.0 cache probes passed on all four targets: 100 interleaved enumerations each after observed native compilation.
  • CRLF-aware diff check passed.
  • CI run 37790547876 succeeded for the exact final commit, with 1,864 passing tests per target and all four native-cache probes passing. Pack and Publish were skipped.
  • The two existing net472 package-support warnings remain for Microsoft.Extensions.Telemetry.Abstractions and Microsoft.Extensions.Diagnostics.Testing 10.0.0. No new compiler/analyzer warnings, failed final checks or blocked checks remain.

Awaiting your review and explicit instruction before starting another issue.

@AGiorgetti
AGiorgetti marked this pull request as ready for review October 8, 2026 14:18
@AGiorgetti
AGiorgetti merged commit 0aafe43 into develop Oct 8, 2026
2 checks passed
@AGiorgetti
AGiorgetti deleted the codex/fix-109-decorator-binding branch October 9, 2026 18:30
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.

Keyed decorator inner binding consumes an explicitly keyed constructor dependency

1 participant