jbogard / MediatR

Simple, unambitious mediator implementation in .NET
Apache License 2.0
10.91k stars 1.16k forks source link

System.InvalidOperationException with KeyedServices in .NET 8 #942

Closed kl1mm closed 8 months ago

kl1mm commented 12 months ago

Hi, I'm currently playing with the new .NET 8 Preview 7 that came out a few days ago.

When I add a KeyedService to the DI container, it causes a System.InvalidOperationException thrown by MediatR.Registration.ServiceRegistrar.RegisterBehaviorIfImplementationsExist.

It seems that the ImplementationType property of ServiceDescriptor is accessed which is not allowed in the case of a "keyed" ServiceDescriptor.

maybe this helps to prepare MediatR for .NET8 KeyedServices?

cheers mMilk

Example to reproduce

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddKeyedSingleton<MyService>("mykey");

// causes System.InvalidOperationException
builder.Services.AddMediatR(cfg =>
{
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
}); 

var app = builder.Build();

app.MapGet("/", (MyService svc) => svc.SayHello());
app.Run();

public class MyService
{
    public string SayHello() => "Hello";
}

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 MediatR.Registration.ServiceRegistrar.<>c.b__12_0(ServiceDescriptor service) at System.Linq.Enumerable.SelectIListIterator2.MoveNext() at System.Linq.Enumerable.OfTypeIterator[TResult](IEnumerable source)+MoveNext() at System.Linq.Enumerable.SelectManySingleSelectorIterator2.MoveNext() at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext() at System.Linq.Enumerable.Any[TSource](IEnumerable1 source, Func2 predicate) at MediatR.Registration.ServiceRegistrar.RegisterBehaviorIfImplementationsExist(IServiceCollection services, Type behaviorType, Type subBehaviorType) at MediatR.Registration.ServiceRegistrar.AddRequiredServices(IServiceCollection services, MediatRServiceConfiguration serviceConfiguration) at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.AddMediatR(IServiceCollection services, MediatRServiceConfiguration configuration)

jbogard commented 12 months ago

How would MediatR support keyed services? Typically when I use keyed services, I don't inject them. I instead resolve them directly from the composition root (the scoped IServiceProvider).

jbogard commented 12 months ago

Ah just adding a keyed service causes this issue? That seems strange, that an accessor throws this exception.

jbogard commented 12 months ago

Yep, this is what broke it: https://github.com/dotnet/runtime/pull/87183/files#diff-90a4b966bf74781df1f355057ad5adca90af0211e46c659965ce745fb0594b5dR157

I don't support keyed services, so I suppose I'll have to explicitly check to see if it's a keyed service and skip them. Annoying.

kl1mm commented 11 months ago

Hey @jbogard, yes it's not that MediatR supports Keyedservices but that the two can coexist in one application.

When I´m right ServiceDescriptor class has a property called IsKeyedService - maybe this helps.

mMilk

jbogard commented 11 months ago

Yeah that's what I'll have to do. Luckily that property is public!

github-actions[bot] commented 9 months ago

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 14 days.

davidfowl commented 9 months ago

I just ran into this and came to file this issue 😄. Assembly scanning is convenient but often fragile 😞.

Dulatr commented 9 months ago

Are there any current workarounds to use both the keyed services feature and mediatr? It doesn't appear possible otherwise.

jbogard commented 9 months ago

@Dulatr use the MyGet feed. The latest is on RC1.

jbogard commented 9 months ago

Realized I didn't push, give it a few minutes and it'll be RC2.

Dulatr commented 9 months ago

@jbogard thanks for the response!

Sorry I've never used MyGet before, what's the feed url?

jbogard commented 9 months ago

There's a link in the readme but you can find it here: https://myget.org/gallery/mediatr-ci

If I was motivated I probably could have put prerelease packages up on NuGet. But like I said. Motivated.

iatsuta commented 8 months ago

Good afternoon, is there any news on solving the problem?

lucasm-optimus commented 8 months ago

I am facing the same issue but more strange is: I am not using any Keyed service in my Azure Functions project.