'MediatR with ASP.NET Core DI

I'm playing around with the new ASP.NET Core and are currently creating a API that I want to call from a JavaScript frontend.

I want to use the mediator pattern to reduce the coupling, and I have found the Library MediatR from Jimmy Bogard.

My problem consist in wiring it up using the build in DI, I have tried looking at the examples, but can't see to crack how it binds into the ConfigureServices method in the startup class.

Do anybody have any insight?

UPDATE: I got it working, from my ConfigureService method:

services.AddScoped<SingleInstanceFactory>(p => t => p.GetRequiredService(t));

services.Scan(scan => scan
        .FromAssembliesOf(typeof(IMediator), typeof(MyHandler.Handler))
        .AddClasses()
        .AsImplementedInterfaces());


Solution 1:[1]

There´s a good tutorial by https://dotnetcoretutorials.com/. This's the example code for the correct installation and configuration of MediatR.

Installing MediatR

The first thing we need to do is install the MediatR nuget package. So from your package manager console run :

Install-Package MediatR

We also need to install a package that allows us to use the inbuilt IOC container in .NET Core to our advantage (We’ll see more of that shortly). So also install the following package :

Install-Package MediatR.Extensions.Microsoft.DependencyInjection

Finally we open up our startup.cs file. In our ConfigureServices method, we need to add in a call to register all of MediatR’s dependencies.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMediatR(Assembly.GetExecutingAssembly());
    //Other injected services. 
}

This is the link: https://dotnetcoretutorials.com/2019/04/30/the-mediator-pattern-part-3-mediatr-library/

I hope this helps.

Solution 2:[2]

I got it working, my code:

public void ConfigureServices(IServiceCollection services)
{
      services.AddScoped<SingleInstanceFactory>(p => t => p.GetRequiredService(t));
      services.AddScoped<MultiInstanceFactory>(p => t => p.GetRequiredServices(t));
      services.Scan(scan => scan
              .FromAssembliesOf(typeof(IMediator), typeof(MyHandlerOne.Handler))
              .FromAssembliesOf(typeof(IMediator), typeof(MyHandlerTwo.Handler))
             .AddClasses()
             .AsImplementedInterfaces());
}

and I have a class that implements the GetRequiredService that MultiInstanceFactory need:

public static class GetServices
{
    public static IEnumerable<object> GetRequiredServices(this IServiceProvider provider, Type serviceType)
    {
        return (IEnumerable<object>)provider.GetRequiredService(typeof(IEnumerable<>).MakeGenericType(serviceType));
    }
}

Solution 3:[3]

Accroding to MediatR documentation to register MediatR service and all handlers you should use AddMediatR method in this way:

public void ConfigureServices(IServiceCollection services)
{
  services.AddMvc();

  services.AddMediatR(typeof(Startup));
}

It's easy , it's comfortable but what if you want to replace one of the handlers? Then you should find oldhandler.cs and remove interface from it so there will be no conflict in ID for more then one implementation.

To avoid this, my advice is to register every handler manually

     public void ConfigureServices(IServiceCollection services)
    {
      services.AddMvc();
    
      services.AddMediatR(typeof(Mediator)); //registering MediatR and all required dependencies
      //registering handlers
      services.AddScoped<IRequestHandler<CreateProductCommand, int>,CreateProductCommandHandler>(); 
      services.AddScoped<IRequestHandler<DeleteProductCommand, int>,DeleteProductCommandHandler>();     

    }

This solution allow you to have multiply handler implementation for the same command and give a control of witch implementation is used

Solution 4:[4]

I created a DI helper for ASP.NET Core RC2 that you can add to your startup. It gives you basic convention based mapping so if you have a class like:

MyClass : IMyClass

It will map IMyClass in the IOC container which will make it available for injection.

I also added the Mappings for MediatR.

To use it Just add the class to your project and then in your startup.cs class add the lines you need to the ConfigureServices() method:

public void ConfigureServices(IServiceCollection services)
{
    //Other Code here......

    var ioc = new PearIoc(services);

    //ioc.AddTransient<IEmailSender, AuthMessageSender>();
    //ioc.AddTransient<ISmsSender, AuthMessageSender>();

    ioc.WithStandardConvention();
    ioc.WithMediatR();
    ioc.RunConfigurations();
}

I added the AddTransient() method just for convenience (you could also just use services.AddTransient()) but it also exposes the IServiceCollection in case you need to do more with it.

You can also extend it like I did with the .WithMediatR() extension and write your own custom mappings.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Carlos de Jesus Baez
Solution 2 Nyegaard
Solution 3 DespeiL
Solution 4 RAM