-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
KeyedService.AnyKey is not usable with ServiceKeyAttribute on object
-typed arguments due to type validation
#93438
Comments
Tagging subscribers to this area: @dotnet/area-extensions-dependencyinjection Issue DetailsDescriptionI'm trying to use the new Keyed services feature, but it looks like the Whenever I try, all combination of types leads to an exception:
This appears to be due to a check that requires the parameter's type to be the same as the one on the registration: runtime/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs Line 580 in 0b25e38
However, this is impossible because I feel like I'm missing something here, but how does Reproduction StepsCreate a new console app under .NET 8 RC2, add the Microsoft.Extensions.DependencyInjection package, and paste this into using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
services.AddKeyedTransient<Service>(KeyedService.AnyKey);
// This line throws
// System.InvalidOperationException: 'The type of the key used for lookup doesn't match the type in the constructor parameter with the ServiceKey attribute.'
using var provider = services.BuildServiceProvider(new ServiceProviderOptions { ValidateOnBuild = true });
// If ValidateOnBuild is false, this line also throws
// System.InvalidOperationException: 'The type of the key used for lookup doesn't match the type in the constructor parameter with the ServiceKey attribute.'
var service = provider.GetKeyedService<Service>("test");
public class Service
{
public Service([ServiceKey] object serviceKey)
{ }
} Expected behavior
Actual behaviorIn both of the above points, a Regression?No response Known WorkaroundsI can workaround by using a factory service registration instead: using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
services.AddKeyedTransient<Service>(KeyedService.AnyKey, (_, key) => new Service(key));
// Validation succeeds now
using var provider = services.BuildServiceProvider(new ServiceProviderOptions { ValidateOnBuild = true });
// Resolving service also succeeds now
var service = provider.GetKeyedService<Service>("test");
public class Service
{
public Service(object serviceKey)
{ }
} Configuration
Other informationNo response
|
PTAL @benjaminpetit |
For |
@benjaminpetit thanks, I didn't notice that, was too focused with having |
Yes, the type check is strict: if you are asking for an |
@benjaminpetit based on
and then later
I assume the type check is strict by design, but we could loosen it up by supporting inheritance? |
@steveharter Just bumped into the issue myself. I guess the type check is not necessary when AnyKey is used. Because semantically AnyKey is exactly what it is - any key. Another (stricter) approach could be limit AnyKey usage to object-typed parameters and to to introduce a generic AnyKeyObj for other parameters. But that would be a breaking change. |
I'm experiencing inverted problem. Trying to get all registered keyed services, but getting empty list. How can I get all registered keyed services from service provider? registration: access: this works: |
This is something we should fix in .NET 10. |
It would be a welcome change! I still have the factory registration workaround setup in a few places |
object
-typed arguments due to type validation
This was fixed in v9: #95582 (you should get back a 2-element array based on |
Based on the discussions above, supporting inheritance for a service constructor parameter using |
Do you mean the comment just above yours regarding |
I hit this today. In my case, I cannot work around it because I have an open generic registration ( I believe this is a bug. M.E.DI has tests which exercise this behavior (eg |
Description
I'm trying to use the new Keyed services feature, but it looks like the
KeyedService.AnyKey
piece is not functional when used in conjunction withServiceKeyAttribute
?E: Issue only occurs when trying to use a base class for the
ServiceKeyAttribute
argument, e.g. in the case below whereobject
is the argument.Whenever I try, all combination of types leads to an exception:
This appears to be due to a check that requires the parameter's type to be the same as the one on the registration:
runtime/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs
Lines 580 to 583 in 0b25e38
However, this is impossible because
KeyedService.AnyKey
uses a dedicated private type and is only exposed asobject
.I feel like I'm missing something here, but how does
KeyedService.AnyKey
work with that strict type check in place?Reproduction Steps
Create a new console app under .NET 8 RC2, add the Microsoft.Extensions.DependencyInjection package, and paste this into
Program.cs
:Expected behavior
KeyedService.AnyKey
for a service that uses the[ServiceKey]
attribute, building the service provider should succeed without validation failuresKeyedService.AnyKey
for a service that uses the[ServiceKey]
attribute, resolving the service using any key input should return the registered implementation and fill in the service key value for the marked parameterActual behavior
In both of the above points, a
System.InvalidOperationException
is thrown insteadRegression?
No response
Known Workarounds
I can workaround by using a factory service registration instead:
Configuration
Other information
No response
The text was updated successfully, but these errors were encountered: