Description
Description
It looks like an intentional behavior is breaking a lot of existing code. There are a lot of places that inspect/iterate over ServiceCollection and look for a specific ImplementationType as a way of custom TryAdd. This works fine with Microsoft.Extensions.DependencyInjection.Abstractions
v8.0.0, until a Keyed descriptor is added before the offending inspection.
This is happening on all frameworks supported by Microsoft.Extensions.DependencyInjection.Abstractions
(v8) - it's not framework-dependent.
Now, I understand that this is not a good practice (iterating and inspecting ImplementationType). Sadly, it seems to be a common practice, even including multiple Microsoft products:
- Live metrics stops working when adding KeyedServices BEFORE AddApplicationInsightsTelemetry() in dotnet 8 rc2 microsoft/ApplicationInsights-dotnet#2828
- .NET 8 WebApi throws InvalidOperationException when keyed Services are registered before MS Identity Services are registered AzureAD/microsoft-identity-web#2604
Problematic source code:
Reproduction Steps
dotnet new console
dotnet add package Microsoft.Extensions.DependencyInjection
Program.cs
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
services.AddKeyedSingleton<FooService>("key");
services.FirstOrDefault(x => x.ImplementationType == typeof(BarService));
class FooService {}
class BarService {}
dotnet run
throws:
Unhandled exception. System.InvalidOperationException: This service descriptor is keyed. Your service provider may not support keyed services.
at Microsoft.Extensions.DependencyInjection.ServiceDescriptor.ThrowKeyedDescriptor()
at Microsoft.Extensions.DependencyInjection.ServiceDescriptor.get_ImplementationType()
at Program.<>c.<<Main>$>b__0_0(ServiceDescriptor x) in C:\Users\amadeusz.sadowski\dev\test-keyed\KeyedExceptionRepro\Program.cs:line 5
at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Func`2 predicate, Boolean& found)
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
at Program.<Main>$(String[] args) in C:\Users\amadeusz.sadowski\dev\test-keyed\KeyedExceptionRepro\Program.cs:line 5
Expected behavior
Existing libraries keep working - exception is not thrown. Maybe just return null.
Actual behavior
InvalidOperationException
is thrown when iterating over registered descriptors' ImplementationType
.
Regression?
Definitely a regression. This works with all versions of DependencyInjection up until v8.
Known Workarounds
Attempt to register keyed service after registrations that inspect ServiceCollection.
Configuration
No response
Other information
No response