Thanks to visit codestin.com
Credit goes to github.com

Skip to content

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

Merged
merged 3 commits into from
Apr 25, 2025

Conversation

steveharter
Copy link
Member

@steveharter steveharter commented Apr 23, 2025

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 a ServiceIdentifier where ServiceIdentifier.ServiceType was always the same as the current TypeDescriptor.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 in KeysMatch(). The fix for this was to remove the check in TryCreateExact() 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.

@steveharter steveharter added this to the 10.0.0 milestone Apr 23, 2025
@steveharter steveharter requested review from halter73 and tarekgh April 23, 2025 20:49
@steveharter steveharter self-assigned this Apr 23, 2025
@Copilot Copilot AI review requested due to automatic review settings April 23, 2025 20:49
Copy link
Contributor

@Copilot Copilot AI left a 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

Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-extensions-dependencyinjection
See info in area-owners.md if you want to be subscribed.

void AddCallSite(ServiceCallSite callSite, int index)
{
slot++;
int GetSlot()
Copy link
Member

@tarekgh tarekgh Apr 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int GetSlot()

can we make these sub-methods statis and pass the needed parameters?

Copy link
Member Author

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.

Copy link
Member

@tarekgh tarekgh left a 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.

Copy link
Contributor

@IliaShuliatikov IliaShuliatikov left a 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.

@steveharter steveharter merged commit 75aee17 into dotnet:main Apr 25, 2025
82 of 86 checks passed
@steveharter steveharter deleted the DiAnyKeySingleton branch April 25, 2025 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants