gpt4 book ai didi

c# - 如何装饰 MediatR 处理程序

转载 作者:行者123 更新时间:2023-12-04 15:49:09 26 4
gpt4 key购买 nike

我只想装饰一个 MediatR 处理程序。我尝试使用 Behaviours,但 Behaviors 为每个实现 IRequestHandler<TRequest,TResponse> 的处理程序注入(inject)了装饰器。

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<,>));
}
}

问题:如何添加一个装饰器,该装饰器将在调用 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);
}
}

最佳答案

如果您要做的只是在调用处理程序之前运行一些东西,那么您可以利用 Behaviors 来实现这一点。我知道你说过你之前已经尝试过这个,但是,你可以创建一个通用的行为来运行 IRequestPreProcessor 的所有实现。
注意:以下过程也适用于在处理程序运行后实现某些内容,您只需将接口(interface)从 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);
}
}
你可以实现 IRequestPreProcessor(你需要的装饰器),但一定要指定你希望它运行的命令
public class PreProcessFirstCommand : IRequestPreprocessor<ProcessFirstCommand>
{
public ProcessFirstCommandHandlerDecorator()
{

}

public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
{
Console.WriteLine("Inside Process First Command Handler Decorator");
}
}
这将由您的通用 PreProcessorBehaviour 激活,它将在每个 MediatR 请求上运行,但只会注入(inject) IRequestPreProcessor 的实现,这些实现使用通用类型或指定 TRequest 类型,就像我们上面的 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);
}
}
注意:这个解决方案唯一的小问题是,如果你使用 ASP .NET Core 的默认依赖注入(inject)器,它只会注入(inject)一个实现 IRequestPreProcessor 并指定类型的类。
例如:
如果您有以下类(class):
ProcessFirstCommandHandler.cs
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);
}
}
预处理第一命令.cs
public class PreProcessFirstCommand : IRequestPreprocessor<ProcessFirstCommand>
{
public ProcessFirstCommandHandlerDecorator()
{

}

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

}

public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
{
Console.WriteLine("I ran before the handler as well!");
}
}
通用预处理命令.cs
public class GenericPreProcessCommand<TRequest> : IRequestPreprocessor<TRequest>
{
public ProcessFirstCommandHandlerDecorator()
{

}

public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
{
Console.WriteLine("I'm generic!");
}
}
另一个通用PreProcessCommand.cs
public class AnotherGenericPreProcessCommand<TRequest> : IRequestPreprocessor<TRequest>
{
public ProcessFirstCommandHandlerDecorator()
{

}

public Task Process(ProcessFirstCommand request, CancellationToken cancellationToken)
{
Console.WriteLine("I'm generic aswell!");
}
}
使用前面提到的通用 PreProcessorBehavior,这将注入(inject) GenericPreProcessCommand 和 AnotherGenericPreProcessCommand,但只注入(inject) PreProcessFirstCommand 或 AnotherPreProcessFirstCommand 之一。这似乎只是 DI 的一个限制。我在 official github issue 上为 MediatR 的创建者 Jimmy Bogard 留下了评论。 ,所以请务必阅读并在那里做出贡献。

关于c# - 如何装饰 MediatR 处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54580769/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com