In-proc event dispatching through IoC container Here is the sender and handler interfaces:
public interface ISender
{
    Task SendAsync(object e);
}

public interface IHandler&lt;in TEvent&gt;
{
    Task HandleAsync(TEvent e);
}

So I register in IoC container a sender service implementation, which dispatches events to all the compatible IHandler&lt;in T&gt; implementations. I use Autofac with a contravariance source, but there could be something else:
[Service]
public class Sender : ISender
{
    public Sender(IServiceProvider provider) =&gt; Provider = provider;
    IServiceProvider Provider { get; }

    public async Task SendAsync(object e)
    {
        var eventType = e.GetType();
        var handlerType = typeof(IHandler&lt;&gt;).MakeGenericType(eventType);
        var handlerListType = typeof(IEnumerable&lt;&gt;).MakeGenericType(handlerType);
        var method = handlerType.GetMethod(&quot;HandleAsync&quot;, new[] { eventType });
        var handlers = ((IEnumerable)Provider.GetService(handlerListType)).OfType&lt;object&gt;();
        await Task.WhenAll(
            handlers.Select(h =&gt;
                Task.Run(() =&gt; (Task)method.Invoke(h, new[] { e }))
                    .ContinueWith(_ =&gt; { })));
    }
}
I think the code would be more readable and easier to maintain if there was a method that handled the main calling of the other handlers.
Unless there is a reason for provider to be a property I would make it a readonly field instead.
public class Sender : ISender
{
    private readonly MethodInfo handlerMethodInfo;
    private readonly IServiceProvider provider;
   
    public Sender(IServiceProvider provider)
    {
        this.provider = provider;
        Func&lt;Task, object&gt; handlerMethod = HandleAsync&lt;object&gt;;
        handlerMethodInfo = handlerMethod.Method.GetGenericMethodDefinition(); 
    }

    private async Task HandleAsync&lt;TEvent&gt;(TEvent e)
    {
        var handlers = provider.GetService&lt;IEnumerable&lt;IHandler&lt;TEvent&gt;&gt;&gt;();
        await Task.WhenAll(handlers.Select(h =&gt; h.HandleAsync(e)));
    }

    public async Task SendAsync(object e)
    {
        // Call the HandleAsync method
        var eventType = e.GetType();
        var method = handlerMethodInfo.MakeGenericMethod(eventType);
        await (Task)method.Invoke(this, new object[] { e });
     }
}

In the constructor just getting a reference to the method needed to call and in a way that's type safe.  Then in the SendAsync we will use reflection to call the private method to call the other classes.  Now the reflection code is a lot smaller but the main logic is still in &quot;normal&quot; code in the HandleAsync method.
We could turn the SendAsync into ExpressionTrees to only require reflection once but they come with a high price.  Typically code would need to be called ~500 to make up the speed hit of compiling the expression vs reflection.