C# 如何装饰MediatR处理程序

C# 如何装饰MediatR处理程序,c#,autofac,cqrs,mediatr,C#,Autofac,Cqrs,Mediatr,我只想装饰一个MediatR处理器。我尝试使用行为,但行为为每个实现IRequestHandler 如果您所要做的只是在调用处理程序之前运行一些东西,那么您可以利用行为来实现这一点。我知道您说过您以前尝试过这个,但是,您可以创建一个generate行为来运行IRequestPrecessor的所有实现 注意:下面的过程用于在处理程序运行后实现某些东西,您只需将IRequestPreProcessor的实现更改为IReqiestPostProcessor即可 因此,如果您有命令处理程序: publ

我只想装饰一个MediatR处理器。我尝试使用行为,但行为为每个实现
IRequestHandler


如果您所要做的只是在调用处理程序之前运行一些东西,那么您可以利用行为来实现这一点。我知道您说过您以前尝试过这个,但是,您可以创建一个generate行为来运行IRequestPrecessor的所有实现

注意:下面的过程用于在处理程序运行后实现某些东西,您只需将IRequestPreProcessor的实现更改为IReqiestPostProcessor即可

因此,如果您有命令处理程序:

public class ProcessFirstCommandHandler : IRequestHandler<ProcessFirstCommand, bool>
{
    public Task<bool> Handle(ProcessFirstCommand request, CancellationToken cancellationToken)
    {
        Console.WriteLine("Inside Process First Command Handler");

        return Task.FromResult(true);
    }
}
公共类ProcessFirstCommandHandler:IRequestHandler
{
公共任务句柄(ProcessFirstCommand请求、CancellationToken CancellationToken)
{
WriteLine(“内部进程第一个命令处理程序”);
返回Task.FromResult(true);
}
}
您可以实现IRequestPreProcessor(您所需的装饰器),但一定要指定要针对其运行的命令

public class PreProcessFirstCommand : IRequestPreprocessor<ProcessFirstCommand>
{

        public ProcessFirstCommandHandlerDecorator()
        {

        }

        public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
        {
            Console.WriteLine("Inside Process First Command Handler Decorator");
        }
}
公共类预处理程序命令:IRequestPreprocessor
{
公共进程FirstCommandHandlerDecorator()
{
}
公共任务进程(ProcessFirstCommand请求、CancellationToken CancellationToken)
{
WriteLine(“内部进程第一个命令处理程序装饰程序”);
}
}
这将由您的泛型预处理行为激活,它将在每个MediatR请求上运行,但只会注入使用泛型类型或指定TRequest类型的IRequestPreProcessor的实现,正如上面的PreProcessFirstCommand类所做的那样:

public class RequestPreProcessValidationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
    {
    private readonly IEnumerable<IRequestPreProcessor<TRequest>> _preProcessors;

    public RequestPreProcessValidationBehaviour(IEnumerable<IRequestPreProcessor<TRequest>> preProcessors)
    {
        _preProcessors = preProcessors;
    }

    public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
    {

        foreach (var processor in _preProcessors)
        {
            await processor.Process(request, cancellationToken).ConfigureAwait(false);
        }

        return await next().ConfigureAwait(false);
    }


}
public类requestPreprocessValidationBehavior:IPipelineBehavior其中TRequest:IRequest
{
私有只读IEnumerable预处理器;
公共请求预处理验证行为(IEnumerable预处理器)
{
_预处理器=预处理器;
}
公共异步任务句柄(TRequest请求、CancellationToken CancellationToken、RequestHandlerDelegate next)
{
foreach(预处理器中的var处理器)
{
等待处理器。进程(请求、取消令牌)。配置等待(false);
}
返回wait next().configurewait(false);
}
}
注意:此解决方案唯一的一个小问题是,如果您使用ASP.NETCore的默认依赖项注入器,它将只注入实现iRequestReprocessor并指定类型的一个类

例如:

如果您有以下课程:

ProcessFirstCommandHandler.cs
公共类ProcessFirstCommandHandler:IRequestHandler
{
公共任务句柄(ProcessFirstCommand请求、CancellationToken CancellationToken)
{
WriteLine(“我在处理程序中”);
返回Task.FromResult(true);
}
}
预处理firstCommand.cs
公共类预处理程序命令:IRequestPreprocessor
{
公共进程FirstCommandHandlerDecorator()
{
}
公共任务进程(ProcessFirstCommand请求、CancellationToken CancellationToken)
{
WriteLine(“我跑在处理程序前面”);
}
}
另一个preprocessfirstCommand.cs
public类另一个prepreprocessfirst命令:IRequestPreprocessor
{
公共进程FirstCommandHandlerDecorator()
{
}
公共任务进程(ProcessFirstCommand请求、CancellationToken CancellationToken)
{
WriteLine(“我也跑在处理程序前面!”);
}
}
GenericCommand.cs
公共类GenericPreprocessor命令:IRequestPreprocessor
{
公共进程FirstCommandHandlerDecorator()
{
}
公共任务进程(ProcessFirstCommand请求、CancellationToken CancellationToken)
{
WriteLine(“我是泛型的!”);
}
}
另一个GenericPreprocessCommand.cs
public类另一个GenericPreprocessor命令:IRequestPreprocessor
{
公共进程FirstCommandHandlerDecorator()
{
}
公共任务进程(ProcessFirstCommand请求、CancellationToken CancellationToken)
{
WriteLine(“我也是泛型的!”);
}
}
使用前面提到的通用预处理命令,这将同时注入GenericPrepreprocessCommand和另一个GenericPreProcessCommand,但只注入PreProcessFirstCommand或另一个PreProcessFirstCommand中的一个。这似乎只是DI的一个限制。我已经给MediatR的创作者Jimmy Bogard在网站上留下了评论,所以请务必在那里阅读并发表意见


祝你好运

在大多数情况下,使用
iRequestReprocessor
是推荐和首选的方法,但您仍然可以直接调用IoC容器来添加装饰器

例如,使用SimpleInjector:

container.RegisterDecorator(typeof(IRequestHandler<,>), typeof(HandlerDecorator<,>));
container.RegisterDecorator(typeof(IRequestHandler),typeof(handlerdecotor));

对上述问题有何指导?任何人
public class RequestPreProcessValidationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
    {
    private readonly IEnumerable<IRequestPreProcessor<TRequest>> _preProcessors;

    public RequestPreProcessValidationBehaviour(IEnumerable<IRequestPreProcessor<TRequest>> preProcessors)
    {
        _preProcessors = preProcessors;
    }

    public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
    {

        foreach (var processor in _preProcessors)
        {
            await processor.Process(request, cancellationToken).ConfigureAwait(false);
        }

        return await next().ConfigureAwait(false);
    }


}
public class ProcessFirstCommandHandler : IRequestHandler<ProcessFirstCommand, bool>
{
    public Task<bool> Handle(ProcessFirstCommand request, CancellationToken cancellationToken)
    {
        Console.WriteLine("I'm inside the handler");

        return Task.FromResult(true);
    }
}
public class PreProcessFirstCommand : IRequestPreprocessor<ProcessFirstCommand>
{

        public ProcessFirstCommandHandlerDecorator()
        {

        }

        public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
        {
            Console.WriteLine("I ran before the handler");
        }
}
public class AnotherPreProcessFirstCommand : IRequestPreprocessor<ProcessFirstCommand>
{

            public ProcessFirstCommandHandlerDecorator()
            {

            }

            public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
            {
                Console.WriteLine("I ran before the handler aswell!");
            }
 }
public class GenericPreProcessCommand<TRequest> : IRequestPreprocessor<TRequest>
{

            public ProcessFirstCommandHandlerDecorator()
            {

            }

            public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
            {
                Console.WriteLine("I'm generic!");
            }
 }
public class AnotherGenericPreProcessCommand<TRequest> : IRequestPreprocessor<TRequest>
{

            public ProcessFirstCommandHandlerDecorator()
            {

            }

            public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
            {
                Console.WriteLine("I'm generic aswell!");
            }
 }
container.RegisterDecorator(typeof(IRequestHandler<,>), typeof(HandlerDecorator<,>));