-
Notifications
You must be signed in to change notification settings - Fork 5k
Fix AnyKey query when there are duplicates and multiple service types #114972
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes an issue with the AnyKey query when duplicate service keys and multiple service types are involved by correctly calculating the int-based slot for each unique key‐type combination. Key changes include refactoring the slot calculation logic in CallSiteFactory.cs, adding distinct slot assignment for AnyKey queries using a keyed dictionary, and adding test coverage in KeyedDependencyInjectionSpecificationTests.cs to verify the ordering and caching behavior.
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
File | Description |
---|---|
src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs | Refactored slot calculation logic and introduced keyed slot assignment for AnyKey queries |
src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/KeyedDependencyInjectionSpecificationTests.cs | Added tests to verify proper ordering and instance resolution across various service registration scenarios |
src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs
Outdated
Show resolved
Hide resolved
src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs
Outdated
Show resolved
Hide resolved
Tagging subscribers to this area: @dotnet/area-extensions-dependencyinjection |
void AddCallSite(ServiceCallSite callSite, int index) | ||
{ | ||
slot++; | ||
int GetSlot() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think keeping it as-is helps since there are 5 variables (isAnyKeyLookup, slot, keyedSlotAssignment, _descriptors, registrationKey) and tight coupling here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added minor comment/suggestion. LGTM otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a similar solution in mind, but was unsure about the performance cost of that new slots dictionary. Even though I can see some potential cases when this dictionary can be allocated multiple times through the application startup/lifetime and potentially have some performance impact, I don't think it's a common case.
I left a couple of comments, other than that LGTM. Thanks for notifying for the review.
Fixes #113472
The fix for the issue above is to calculate the int-based "slot" correctly for each set of unique service keys (including its service type) during a AnyKey query. The slot is used to preserve ordering and included in the identity in the result caches. The fix is to use a Dictionary to maintain the correct slot for each set of unique service keys during the AnyKey query. This is only required the first time an AnyKey query is performed for a given service type since the result is cached after that.
In addition, there was an unreported issue found where a call to
TryCreateExact()
method was passing aServiceIdentifier
whereServiceIdentifier.ServiceType
was always the same as the currentTypeDescriptor.ServiceType
, causing services of different types to be included in the AnyKey query result, but only if the key matched, which was checked for previously inKeysMatch()
. The fix for this was to remove the check inTryCreateExact()
and create a new method so it can be called by just passing in the type of the descriptor and type of the lookup key.cc @IliaShuliatikov for review.