-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Dependency injection: FromKeyedServiceAttribute falls back to last defined unkeyed service of the type -- unexpected behavior? #102654
Comments
Tagging subscribers to this area: @dotnet/area-system-serviceprocess |
@dotnet/area-extensions-dependencyinjection |
Tagging subscribers to this area: @dotnet/area-extensions-dependencyinjection |
Surprised by this behavior. I agree it looks weird and should not be like that: This "fallback" behavior, if intentional, should at least be behind a bool setting in the attribute, something like: public record ServiceWhichAcceptsKeyedService(
[FromKeyedServices("myKey", FallbackToNonKeyed = true)] IService service); Where |
It definitely looks more like a bug than a feature... This was a nasty surprise that we've hit now while implementing #89755 (HttpClientFactory support for keyed DI) -- will the fix make it to 9.0? @steveharter @benjaminpetit Come context: HttpClientFactory is a singleton service that configures ( Lines 65 to 69 in 8c95a64
#89755 is about allowing to use [FromKeyedServices] to inject the required configured Named Current behavior unfortunately means that every Named cc @dotnet/ncl @halter73 @davidfowl |
Agreed. A parameter attributed with I think we should patch .NET 8 to fix this. I cannot imagine on anyone relying on this behavior. And if anyone is relying on that behavior, we should nip that in the bud. |
If it's there, it's being relied on by someone. If you are patching .NET 8, consider putting it behind an app setting. |
This appears to be a duplicate of #102204 which was recently fixed. |
Description
I'm currently in a repo where we might need a mix of keyed and unkeyed services. For the specific case, various types of a service are configured, and injected through an
IEnumerable
. The keyed dependency would be used to retrieve a default one for some specific cases. We've been able to work around it, but I was surprised by the behavior, so I just want to check if this behavior is intended.When configuring a service which has a constructor argument with the attribute
[FromKeyedServices("myKey")]
on an argument - if that service was not configured with the key, I will get injected the last one which was configured without a key.This seems like a corner case, and in my mental model, I'd expect to get an exception if the argument is non-nullable, or null if it were. If the typing system makes that challenging, an option could be to add another attribute:
FromRequiredKeyedService
which would throw if the service is missing.Reproduction Steps
The test called
ShouldNotGetServiceIfKeyedIsNotAdded
demonstrates the issueExpected behavior
Test called
ShouldNotGetServiceIfKeyedIsNotAdded
should succeed - I would expect it not to resolve the service when I request a keyed service, and no keyed service is defined.Actual behavior
The test called
ShouldNotGetServiceIfKeyedIsNotAdded
fails - I get the last configured unkeyed service of the type.Regression?
No response
Known Workarounds
Explicitly taking a serviceProvider, and calling
GetKeyedService
orGetRequiredKeyedService
works.(for the types not defined in this example, see their implementation in the reproduction steps)
Configuration
Other information
No response
The text was updated successfully, but these errors were encountered: