使用MediatR链接处理程序

9
我们正在使用MediatR实现dotnet core WebAPI后端的“Pipeline”,尝试遵循CQRS原则。我无法决定是否应该尝试实现一个“IPipelineBehavior”链,或者是否更好地构建一个新请求并从处理程序方法(用于请求)中调用MediatR.Send。
场景基本如下: 1. 用户请求执行某个操作,例如删除某些内容。 2. 我们必须检查是否有其他人在使用这些内容。 3. 我们必须将这些内容标记为已删除。 4. 我们必须从文件系统中实际删除这些文件。
我们现在采用的是“Option 1”:一个“DeleteRequest”由一个类处理,在其中处理程序检查它是否正在使用,将其标记为已删除,然后发送一个带有参数的新“TaskStartRequest”以进行删除。
我正在考虑的是“Option 2”:一个“DeleteRequest”实现了标记接口“IRequireCheck”、“IStartTask”,具有运行以下流程的管道: 1. 首先使用“IPipelineBehavior<IRequireCheck>”检查是否正在使用某些内容。 2. 使用“IPipelineBehavior<DeleteRequest>”将这些内容标记为已删除。 3. 使用“IPipelineBehavior<IStartTask>”启动任务。
我还没有完全想清楚Option 2会是什么样子,但这是大致的想法。我主要想知道,在处理程序中为TRequest1调用MediatR.Send(TRequest2)是否属于代码异味。

1
你能够实现你的第二个选项吗?我发现关于管道和行为方面的文档不足,无法为我提供足够的背景来将它们翻译到我的情况中,这与你的第2个选项类似。 - Nate
我们还没有实现那个功能,它还不是我们的优先事项,但很快就会了。不过我学到了一些有趣的关于注册管道处理程序的知识,这使得这个功能更可行了。我们对身份验证、审计日志和其他一些横切关注点也做类似的事情。 - gakera
实质上,我们使用反射来注册标记接口类的处理程序,以便它们正确地注册为相应请求或响应类型的预处理器或后处理器。我们将其用于IAddToAuditLog等标记接口。 - gakera
2个回答

2
如果你决定采用这些选项,我会推荐选择第二个选项。从现有的 Mediatr 处理程序中发送请求可能被视为代码异味。你隐藏了副作用并破坏了单一职责原则。你也将请求耦合在一起,应该尽量避免无法在另一个请求之前发送某种类型的请求的情况。
然而,我认为可能有一种替代方案。如果删除请求不能在验证和标记之前发生,你可以利用预处理器(这里有一个示例)来处理你的TaskStartRequest。这样你就可以有一个单一的请求来完成你需要的所有操作。这甚至通过简单地利用现有的 Mediatr 模式来镜像你的管道示例。

1
如果第一次或第二次检查失败了,我们如何停止其余的处理呢?在管道实现中,我认为我必须调用next()来继续处理,所以如果它失败了,我可以跳过调用next()。 - gakera
1
嗯,这是一个很好的观点。过去我会抛出异常。因此,如果我们要删除的项目不存在,我会抛出一个自定义异常,在中间件中处理以产生404结果。如果您不想使用异常,我认为您的管道想法仍然更好。然后,您将能够在没有异常的情况下控制执行。 - Donald McPartland

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

1
这个选项假设thing能够确定它是否正在被使用,但并非总是如此。 - Nate
在我们的情况下,这不仅仅是从repo中删除,还要启动一个任务来删除文件。任务使用不同的处理器启动,就像我之前提到的那样,我不喜欢从处理程序的正文发送不同的请求。 - gakera
2
发送通知而不是请求任务开始,这样做有意义吗?请参见 https://github.com/jbogard/MediatR/issues/237 了解类似的问题。 - Oldrich Dlouhy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接