Rup*_*esh 6 c# autofac cqrs mediatr
我只想装饰一个 MediatR 处理程序。我尝试使用行为,但行为为每个实现的处理程序注入装饰器IRequestHandler<TRequest,TResponse>
public class ProcessFirstCommand : IRequest<bool>
{
public string Message { get; set; }
}
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);
}
}
public class Manager
{
private readonly IMediator _mediator;
public Manager(IMediator mediator)
{
_mediator = mediator;
}
public void Execute()
{
_mediator.Send(new ProcessFirstCommand());
}
}
//Registering in Autofac for IRequestHandler
public class Module : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(ThisAssembly)
.AsClosedTypesOf(typeof(IRequestHandler<,>));
}
}
Run Code Online (Sandbox Code Playgroud)
问题:如何添加一个装饰器,该装饰器将在调用 ProcessFirstCommandHandler 类的 Handle 方法之前执行,而不是在实现 IRequestHandler 的其他类中执行。
当 Manager 对象执行此行时,如何在 ProcessFirstCommandHandler 之前首先调用下面的类 Handle 方法_mediator.Send(new ProcessFirstCommand());
public class ProcessFirstCommandHandlerDecorator<TRequest, TResponse> : IRequestHandler<ProcessFirstCommand, bool>
where TRequest : ProcessFirstCommand
{
private readonly IRequestHandler<ProcessFirstCommand, bool> _handler;
public ProcessFirstCommandHandlerDecorator(IRequestHandler<ProcessFirstCommand, bool> handler)
{
_handler = handler;
}
public Task<bool> Handle(ProcessFirstCommand request, CancellationToken cancellationToken)
{
Console.WriteLine("Inside Process First Command Handler Decorator");
_handler.Handle(request, cancellationToken);
return Task.FromResult(true);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 3
如果您想做的只是在调用处理程序之前运行一些东西,那么您可以利用行为来实现这一点。我知道您说过您以前尝试过此操作,但是,您可以创建一个运行 IRequestPreProcessor 的所有实现的通用行为。
注意:以下过程也适用于在处理程序运行后实现某些内容,您只需将接口从 IRequestPreProcessor 更改为 IRequestPostProcessor
因此,如果您有命令处理程序:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
您可以实现 IRequestPreProcessor (您所需的装饰器),但请务必指定您希望其运行的命令
public class PreProcessFirstCommand : IRequestPreprocessor<ProcessFirstCommand>
{
public ProcessFirstCommandHandlerDecorator()
{
}
public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
{
Console.WriteLine("Inside Process First Command Handler Decorator");
}
}
Run Code Online (Sandbox Code Playgroud)
这将由通用 PreProcessorBehaviour 激活,它将在每个 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);
}
}
Run Code Online (Sandbox Code Playgroud)
注意:此解决方案唯一的小问题是,如果您使用 ASP .NET Core 的默认依赖项注入器,它只会注入实现 IRequestPreProcessor 并指定类型的类之一。
例如:
如果您有以下课程:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
public class PreProcessFirstCommand : IRequestPreprocessor<ProcessFirstCommand>
{
public ProcessFirstCommandHandlerDecorator()
{
}
public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
{
Console.WriteLine("I ran before the handler");
}
}
Run Code Online (Sandbox Code Playgroud)
public class AnotherPreProcessFirstCommand : IRequestPreprocessor<ProcessFirstCommand>
{
public ProcessFirstCommandHandlerDecorator()
{
}
public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
{
Console.WriteLine("I ran before the handler as well!");
}
}
Run Code Online (Sandbox Code Playgroud)
public class GenericPreProcessCommand<TRequest> : IRequestPreprocessor<TRequest>
{
public ProcessFirstCommandHandlerDecorator()
{
}
public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
{
Console.WriteLine("I'm generic!");
}
}
Run Code Online (Sandbox Code Playgroud)
public class AnotherGenericPreProcessCommand<TRequest> : IRequestPreprocessor<TRequest>
{
public ProcessFirstCommandHandlerDecorator()
{
}
public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
{
Console.WriteLine("I'm generic aswell!");
}
}
Run Code Online (Sandbox Code Playgroud)
使用前面提到的通用 PreProcessorBehavior,这将注入GenericPreProcessCommand和AnotherGenericPreProcessCommand ,但仅注入PreProcessFirstCommand或AnotherPreProcessFirstCommand之一。这似乎只是 DI 的一个限制。我已经在官方 github 问题上为 MediatR 创建者 Jimmy Bogard 留下了评论,所以请务必阅读并在那里做出贡献。