Skip to content

ServiceDescriptor.ImplementationType throws exception for Keyed descriptor: System.InvalidOperationException: This service descriptor is keyed. Your service provider may not support keyed services. #95789

Closed
@amis92

Description

@amis92

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:

Problematic source code:

public Type? ImplementationType
{
get
{
if (IsKeyedService)
{
ThrowKeyedDescriptor();
}
return _implementationType;
}
}

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

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions