jbogard / MediatR

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

Dynamic dispatch no longer working since upgrading to 12.0.1 from 11.1.0 #867

Closed paulb2015 closed 1 year ago

paulb2015 commented 1 year ago

Since upgrading from 11.1.0 to 12.0.1, dynamic dispatch no longer works and a RuntimeBinderException is thrown.

Code using 12.0.1:

public class Ping : IRequest<string>
{
}

public class PingHandler : IRequestHandler<Ping, string>
{
    public Task<string> Handle( Ping request, CancellationToken cancellationToken )
    {
        return Task.FromResult( "Pong" );
    }
}

internal class Program
{
    static async Task Main( string[] args )
    {
        var serviceProvider = new ServiceCollection().AddMediatR( p => p.RegisterServicesFromAssemblyContaining<Program>() ).BuildServiceProvider();
        var mediator = serviceProvider.GetRequiredService<IMediator>();
        var json = JsonConvert.SerializeObject( new Ping() );

        dynamic request = JsonConvert.DeserializeObject( json, typeof( Ping ) );

        var result = await mediator.Send( request );

        Console.WriteLine( result );
    }
}

Result: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'The type 'Ping' cannot be used as type parameter 'TRequest' in the generic type or method 'MediatR.ISender.Send<TRequest>(TRequest, System.Threading.CancellationToken)'. There is no implicit reference conversion from 'Ping' to 'MediatR.IRequest'.'

Code using 11.1.0:

public class Ping : IRequest<string>
{
}

public class PingHandler : IRequestHandler<Ping, string>
{
    public Task<string> Handle( Ping request, CancellationToken cancellationToken )
    {
        return Task.FromResult( "Pong" );
    }
}

internal class Program
{
    static async Task Main( string[] args )
    {
        var serviceProvider = new ServiceCollection().AddMediatR( typeof( Program ) ).BuildServiceProvider();
        var mediator = serviceProvider.GetRequiredService<IMediator>();
        var json = JsonConvert.SerializeObject( new Ping() );

        dynamic request = JsonConvert.DeserializeObject( json, typeof( Ping ) );

        var result = await mediator.Send( request );

        Console.WriteLine( result );
    }
}

Result: Pong

jbogard commented 1 year ago

There was a new overload added, maybe cast to object first? Which overload is being used here?

paulb2015 commented 1 year ago

It's using:

Task<TResponse> Send<TResponse>( IRequest<TResponse> request, CancellationToken cancellationToken = default( CancellationToken ) );

Casting to an object solves the problem.

Thank you

github-actions[bot] commented 1 year 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.