Skip to content

Prefer a complete generic argument mapping for multi-interface open generics (#1464) - #1489

Merged
tillig merged 3 commits into
developfrom
feature/issue-1464
Jun 15, 2026
Merged

Prefer a complete generic argument mapping for multi-interface open generics (#1464)#1489
tillig merged 3 commits into
developfrom
feature/issue-1464

Conversation

@tillig

@tillig tillig commented Jun 15, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #1464. When an open-generic implementation implements multiple interfaces matching the registered service pattern, and the first matching interface candidate could not actually map its generic arguments to the implementation's type parameters (e.g. IHandler<IRequest> appearing before IHandler<IRequest<TParam>>), TryMapImplementationGenericArguments returned that broken candidate via the availableArguments[0] fallback. The result was a valid registration being silently dropped from resolved enumerables.

Fix

In OpenGenericServiceBinder.TryMapImplementationGenericArguments, when there is no exact match, the binder now prefers the first candidate that produces a complete mapping (every implementation type parameter resolved — no null entries), falling back to availableArguments[0] only when no candidate maps completely. This preserves prior behavior for genuinely un-bindable cases. The single-interface and exact-match paths are unchanged.

The "complete mapping" check (a.All(arg => arg is not null)) mirrors the check the caller already performs, keeping the semantics consistent.

Second case (IHandler<int> registered as IHandler<>)

A type like Handler<TParam> : IHandler<int> registered against the open IHandler<> still correctly produces no resolution result (the closed int argument leaves TParam un-inferable), with no exception and no incorrect binding — same as before the fix. If registration-time rejection of such cases is desired, that's a separate issue.

Tests

Adds 4 tests in OpenGenericMultipleInterfaceOrderTests: mappable-interface-first resolves; non-mappable-interface-first resolves (the #1464 regression); both order variants resolve from a single enumerable; and the unrelated-type-param case resolves to empty. All 155 existing open-generic tests pass.

No public API changes. Zero warnings/errors; full suites pass on net8.0 and net10.0.

…h service pattern (#1464)

When an open-generic implementation type implements multiple interfaces that match
the service's name/namespace pattern (e.g. IHandler<IRequest> and IHandler<IRequest<TParam>>),
TryMapImplementationGenericArguments previously fell back to availableArguments[0] when no
exact match existed. If the first candidate produced an incomplete mapping (null entries
because its generic args could not be resolved to the implementation's type parameters),
the caller's null check would fail and the registration was silently dropped.

Fix: after the exact-match check, prefer the first candidate that produces a complete
mapping (no null entries). Only fall back to availableArguments[0] when no candidate
maps fully, preserving existing behavior for genuinely un-bindable registrations.
@codecov

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.91%. Comparing base (f8d4095) to head (4597770).
⚠️ Report is 9 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #1489      +/-   ##
===========================================
+ Coverage    77.69%   77.91%   +0.21%     
===========================================
  Files          217      217              
  Lines         5829     5877      +48     
  Branches      1253     1259       +6     
===========================================
+ Hits          4529     4579      +50     
+ Misses         764      760       -4     
- Partials       536      538       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tillig
tillig merged commit 41a60d6 into develop Jun 15, 2026
12 checks passed
@tillig
tillig deleted the feature/issue-1464 branch June 15, 2026 23:34
This was referenced Jun 17, 2026
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.

OpenGenericServiceBinder.TryBindOpenGenericTypedService behavior does not match assignability rules for uncommon edgecase

1 participant