使用MediatR

时间:2019-09-24 15:50:53

标签: .net-core architecture cqrs mediatr

我们正在使用MediatR为我们的dotnet核心WebAPI后端实现“管道”,以尝试遵循CQRS原则。

我无法决定是否应该尝试实现IPipelineBehavior链,还是最好构造一个新的Request并从我的Handler方法(针对该请求)中调用MediatR.Send。

实际情况是这样的:

  • 用户请求执行一项操作,即删除某些内容
  • 我们必须检查其他人是否正在使用某些东西
  • 我们必须将某些内容标记为已在数据库中删除
  • 我们实际上必须从文件系统中删除文件。

选项1 是我们现在拥有的:DeleteRequest,由一个类处理,其中,处理程序检查是否正在使用它,将其标记为已删除,然后发送新的TaskStartRequest,其参数为Delete。

选项2 是我正在考虑的:一个DeleteRequest,它通过运行以下管道来实现标记接口IRequireCheckIStartTask

  1. IPipelineBehavior<IRequireCheck>首先检查是否正在使用某些东西,
  2. IPipelineBehavior<DeleteRequest>标记某项已在数据库中删除,并且
  3. IPipelineBehavior<IStartTask>以启动任务。

我还没有完全弄清楚选项2是什么样子,但这是一般性的想法。

我想我主要是想知道在THandler1的Handler中调用MediatR.Send(TRequest2)是否有代码味道。

2 个答案:

答案 0 :(得分:1)

如果这些是您要使用的选项-我说的是选项2。从现有Mediatr处理程序内部发送请求可以视为一种代码味道。您隐藏了副作用并违反了单一责任原则。您还将请求合并在一起,应该避免出现无法先发送一种请求的情况。

但是,我认为可能还有其他选择。如果没有验证和事先标记就无法发生删除请求,则可以为TaskStartRequest使用预处理器(example here)。这样,您可以拥有一个可以满足您所有需求的单个请求。这甚至可以通过简单地利用现有Mediatr模式来反映您的管道示例。

答案 1 :(得分:0)

是否需要将任务分成多个Handlers?也许我错过了mediatr中的要点。这样就够了吗?

public async Task<Result<IFailure,ISuccess>> Handle(DeleteRequest request)
{
  var thing = await this.repo.GetById(request.Id);

  if (thing.IsBeignUsed())
  {
    return Failure.BeignUsed();
  }
  var deleted = await this.repo.Delete(request.Id);
  return deleted ? new Success(request.Id) : Failure.DbError();
}