7

I am using the Mediatr in my .Net Core project and I was wondering if the handler's in the Mediatr are singleton's or are the new instances for every Send request; I know the Mediatr is a Singleton' but for the handlers it uses for a command or query, I am not very sure.

I tend to think they would also be singletons; but just wanted to double confirm.

Dhiru
  • 159
  • 2
  • 5

3 Answers3

5

In fact, lifetime of all those things are it's well documented https://github.com/jbogard/MediatR.Extensions.Microsoft.DependencyInjection/blob/master/README.md

Just for reference: IMediator is transient (not a singleton), IRequestHandler<> concrete implementations is transient and so on so actually it's transient everywhere.

But be aware of using Scoped services with Mediatr handlers, it works not as expected, more like singletons, unless you manually create a scope.

Danila Polevshchikov
  • 2,228
  • 2
  • 24
  • 35
4

For the handlers, after following the source code, it looks like they are all added as Transient.

https://github.com/jbogard/MediatR.Extensions.Microsoft.DependencyInjection/blob/1519a1048afa585f5c6aef6dbdad7e9459d5a7aa/src/MediatR.Extensions.Microsoft.DependencyInjection/Registration/ServiceRegistrar.cs#L57

services.AddTransient(@interface, type);

For the IMediator itself, it looks like it is lifetime by default :

https://github.com/jbogard/MediatR.Extensions.Microsoft.DependencyInjection/blob/1519a1048afa585f5c6aef6dbdad7e9459d5a7aa/src/MediatR.Extensions.Microsoft.DependencyInjection/Registration/ServiceRegistrar.cs#L223

services.Add(new ServiceDescriptor(typeof(IMediator), serviceConfiguration.MediatorImplementationType, serviceConfiguration.Lifetime));

Note that the service configuration is a configuration object that unless somehow you change it along it's default path, will be set to transient too :

public MediatRServiceConfiguration()
{
    MediatorImplementationType = typeof(Mediator);
    Lifetime = ServiceLifetime.Transient;
}
MindingData
  • 11,924
  • 6
  • 49
  • 68
0

Using core you can manually register your handlers and use whatever scope you want. So for example:

services.AddScoped<IPipelineBehavior<MyCommand>, MyHandler>();

We actually wrap Mediatr so we can add various bits and bobs so it ends up being a registration extension like this (CommandContect/QueryContext holds various stuff we use all the time and ExecutionResponse is a standard response so we can have standard post handlers that know what they are getting):

public static IServiceCollection AddCommandHandler<THandler, TCommand>(this IServiceCollection services)
            where THandler : class, IPipelineBehavior<CommandContext<TCommand>, ExecutionResponse>
            where TCommand : ICommand
        {
            services.AddScoped<IPipelineBehavior<CommandContext<TCommand>, ExecutionResponse>, THandler>();
            return services;
        }

Which is used like this:

services.AddCommandHandler<MyHandler, MyCommand>();

We have similar for queries (AddQueryHandler<.....)

Hope that helps

PaulD
  • 206
  • 1
  • 5