Mediatr: .NET Core scoped dependency injection not working with MediatR

Created on 6 Aug 2019  路  1Comment  路  Source: jbogard/MediatR

Consider the following code:

Startup.cs

```c#
public static void RegisterServices(IServiceCollection services)
{
services.AddSingleton();
services.AddTransient(); // Empty/dummy interface and class
services.AddMediatR(typeof(AnsweredQuestionCommandHandler));
}

**RabbitMQBus.cs**

```c#
public sealed class RabbitMQBus : IEventBus
{
    private readonly IMediator _mediator;
    private readonly Dictionary<string, List<Type>> _handlers;
    private readonly List<Type> _eventTypes;
    private readonly IServiceScopeFactory _serviceScopeFactory;

    public RabbitMQBus(IMediator mediator, IServiceScopeFactory serviceScopeFactory)
    {
        _mediator = mediator;
        _serviceScopeFactory = serviceScopeFactory;
        _handlers = new Dictionary<string, List<Type>>();
        _eventTypes = new List<Type>();
    }

    public Task SendCommand<T>(T command) where T : Command
    {
        return _mediator.Send(command);
    }
...
}

AnsweredQuestionCommandHandler.cs

```c#
public class AnsweredQuestionCommandHandler : IRequestHandler
{
private readonly IEventBus _bus;
private readonly IStuff _stuff;

public AnsweredQuestionCommandHandler(IEventBus bus, IStuff stuff)
{
    _bus = bus;
    _stuff = stuff;
}

...
}
```
Can someone explain why injecting a Stuff with Transient or Singleton lifetime works as expected--when SendCommand() is invoked, the constructor for AnsweredQuestionCommandHandler is called, Stuff is injected--but if inject it with Scoped lifetime, not only is Stuff never injected, but in fact the constructor for AnsweredQuestionCommandHandler is never even called when SendCommand() is invoked?

Most helpful comment

Ohhhh Singleton's can't depend on anything but Singleton or Transient. Anything a Singleton depends on is automatically elevated to Singelton.

In your code, don't inject an IMediator. Instead, use the IServiceScopeFactory to resolve a scope, and instantiate your IMediator from that scoped IServiceProvider.

This is exactly what ASP.NET Core does for each request:

https://github.com/aspnet/AspNetCore/blob/bae733151be352eed77c07dcdc13d87862a68477/src/Http/Http/src/Features/RequestServicesFeature.cs#L31

Singletons can depend on Singletons
Scoped can depend on Singletons, Transients, and Scoped
Transients can depend on Singletons, Transients, and Scoped

>All comments

Ohhhh Singleton's can't depend on anything but Singleton or Transient. Anything a Singleton depends on is automatically elevated to Singelton.

In your code, don't inject an IMediator. Instead, use the IServiceScopeFactory to resolve a scope, and instantiate your IMediator from that scoped IServiceProvider.

This is exactly what ASP.NET Core does for each request:

https://github.com/aspnet/AspNetCore/blob/bae733151be352eed77c07dcdc13d87862a68477/src/Http/Http/src/Features/RequestServicesFeature.cs#L31

Singletons can depend on Singletons
Scoped can depend on Singletons, Transients, and Scoped
Transients can depend on Singletons, Transients, and Scoped

Was this page helpful?
0 / 5 - 0 ratings