Base solution for your next web application
Open Closed

How to register plugin modules to MediatR ? #9881


User avatar
0
ivanosw1 created

Prerequisites

  • What is your product version? 9.3.0
  • What is your product type (Angular or MVC)? Angular
  • What is product framework type (.net framework or .net core)? Core

If issue related with ABP Framework

  • What is ABP Framework version? 5.14.0

Hi, I need to user the MediatR library but I have a problem with the registration of interfaces. My code is loaded through plugins directory so I need to manually discover the assemblies because are not referenced directly. In the ConfigureServices, just after services.AddAbp<... I have this code:

var pluginTypes = AppDomain.CurrentDomain.GetAssemblies() .AsParallel() .Where(a =&gt; a.FullName.StartsWith("MyDll.")) .SelectMany(x => x.GetTypes()) .ToArray(); services.AddMediatR(pluginTypes);

But at this point, my plugins aren't not loaded yet and so AddMediatR fails.

I do the same with SignalR but it works because is after app.UseAbp in Configure method.

So, how can I register my plugins to MediatoR ?

Thank you.


4 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @ivanosw1

    Did you figure this out ? If not, could you try it after UseAbp ?

    Thanks,

  • User Avatar
    0
    ivanosw1 created

    Hi @ismcagdas, I've made may attempts. After UseAbp is not possibile beacause the extension method AddMediatR(...) is on IServiceCollection that isn't available on Configure method.

    After looking at the examples and what does this extesion https://github.com/jbogard/MediatR.Extensions.Microsoft.DependencyInjection, I ended up with this results:

    Scenario: Framework and 2 plugin modules:

    1. Startup -> ConfigureServices -> before the last return, add thie 3 line of code:
    services.AddMediatR(typeof(Startup));
    services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));
    services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPostProcessorBehavior<,>));
                
    
    1. In every module, in the Initilize() register all RequestHandler and INotificationHandler
    IocManager.RegisterAssemblyByConvention(typeof(MyModule).GetAssembly());
               
    IocManager.Register<IRequestHandler<PingCommand, string>, PingHandler>(DependencyLifeStyle.Transient); //Request/Response
    IocManager.Register<IRequestHandler<PingCommandOneWay,Unit>, PingHandlerOneWay>(DependencyLifeStyle.Transient); //Request
    IocManager.Register<INotificationHandler<PingNotification>, Pong1>(DependencyLifeStyle.Transient); //Notification
    IocManager.Register<INotificationHandler<PingNotification>, Pong2>(DependencyLifeStyle.Transient); //Notification
    
    //Pipelines
    IocManager.IocContainer.Register(Component.For(typeof(IPipelineBehavior<,>)).ImplementedBy(typeof(LoggingBehavior<,>)).LifestyleTransient());
    IocManager.IocContainer.Register(Component.For(typeof(IPipelineBehavior<,>)).ImplementedBy(typeof(ValidationBehaviour<,>)));
    
    //Pre-Post processor            IocManager.IocContainer.Register(Component.For(typeof(IRequestPreProcessor<>)).ImplementedBy(typeof(GenericPreProcessor<>)).LifestyleTransient());
    IocManager.IocContainer.Register(Component.For(typeof(IRequestPostProcessor<,>)).ImplementedBy(typeof(GenericPostProcessor<,>)).LifestyleTransient());
    
    //CatchAll notifications (See point  no.3 for this)
    IocManager.Register<INotificationHandler<INotification>, PongAll>(DependencyLifeStyle.Transient);
                
    
    1. In order to intercept all notification, in only one module, add also this code:
    IocManager.IocContaine.Kernel.AddHandlersFilter(new ContravariantFilter());
    
    public class ContravariantFilter : IHandlersFilter
            {
                public bool HasOpinionAbout(Type service)
                {
                    if (!service.IsGenericType)
                        return false;
    
                    var genericType = service.GetGenericTypeDefinition();
                    var genericArguments = genericType.GetGenericArguments();
                    return genericArguments.Count() == 1
                           && genericArguments.Single().GenericParameterAttributes.HasFlag(GenericParameterAttributes.Contravariant);
                }
    
                public IHandler[] SelectHandlers(Type service, IHandler[] handlers)
                {
                    return handlers;
                }
            }
            
    

    All this seems to works as expected, but is only a sort of cut&paste of AddMediatR with some Abp behaviours. I would be appreciate if you can officially integrate MediatR on Abp or at least validate how manually do.

    Thank you very much.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Yes, you can use this approach at the moment. Could you create an issue on https://github.com/aspnetboilerplate/aspnetboilerplate/, so we can plan about MediatR.

  • User Avatar
    0
    ivanosw1 created

    Ok, I've created the issue

    Thank you.