具有 MediatR 的 CQRS 和命令的可重用性

CQRS with MediatR and re-usability of commands

创建仅包含对象的命令是否有意义?例如:

public class CreateCommand : IRequest
{
   SomeDTO SomeDTO { get; set; }
}

public class UpdateCommand : IRequest
{
   SomeDTO SomeDTO { get; set; }
}

或者可能是这样的(推导):

public class UpdateCommand : SomeDTO, IRequest
{
}

或者 commands/requests 本身应该被视为 DTO?我很困惑,因为我看到了很多做事的方法。将所有属性复制到 command/request 类 听起来也不是一件好事。

你是如何在你的项目中做到这一点的?

您是将命令直接映射到域模型,还是仅使用命令来传递 DTO?

如果使用 MVC 框架,我的控制器操作的输入应该是什么?它应该是一个命令,还是应该在我的操作实现中创建命令并发送它? (我想这将取决于我如何建模我的命令)

您应该将此命令视为 "verbal sentence" 指示您的域执行某些操作。例如 "UpdateCommand" 指示您的域更新某些内容。在命令中你应该包括命令的细节(在你的情况下 dto 很好)...

但是要非常小心那些 DTO。您不希望您的域依赖于 MVC,但相反。确保 dto 所在的程序集不属于比域逻辑更高的级别(在 MVC 的方向上)。

在您的 MVC 中,您应该只有:

  • 依赖注入设置
  • 控制器和视图

控制器应仅包含从方法 (http) 参数( 不安全)转换为域所需的 dto 并调用域所需的代码。

至少我是这样做的。

命令和域objects,至少在我的世界里,有不同的设计约束。特别是,命令是 API 表面的一部分——它们是与其他服务的契约的一部分——因此需要在很长一段时间内具有兼容的定义。另一方面,域 objects 是我们当前做事方式的局部 - 它们是我们在 黑匣子内组织数据的一部分。所以我们可以按照我们喜欢的任何节奏更改它们。

跨越进程边界的命令是消息,也就是说byte[]s。这就是需要在形式和语义上保持稳定的位。

byte[] 与域无关,并且在 "parsing" 消息

中通过其他几个与域无关的中间阶段是相当普遍的
byte[] -> utf8
utf8 -> DOM
DOM -> Dictionary
...

但我们通常会朝着 特定领域 合同表达的方向发展。

见,例如Mark Seemann

At the boundaries, applications are not object-oriented. A DTO is a representation of such a piece of data mapped into an object-oriented language.

byte[]强制转换成方便查询的形式,然后我们可以开始考虑要不要用那个数据开始初始化"objects".

您可能会问的另一个问题 - 在通用元数据中包含消息数据是否有价值 "envelope"。这种模式一直存在——最熟悉的例子是 HTTP POST 是一堆通用的 headers 附加到 message-body.

数据和元数据当然是不同的问题;在您的解决方案中让它们与众不同绝对有意义。

我认为组合数据结构而不是继承它们将是更易于维护的选择。

public class Envelope<Message> ....

可能是一个合理的起点。

Does it make sense to create commands that just hold objects?

不,没有附加值class:没有语义,没有行为...

Or commands/requests should be treated as DTOs themselves?

命令(在术语 中)本质上是 DTO。它们是在 layers/tiers.

之间循环的哑数据包

Do you map your commands directly to your domain models

这取决于您是否喜欢 task-based UI 而不是基于 CRUD 的 UI。如果你做 DDD/rich 领域模型——有些人甚至会说基本的 OO 封装——你就不会映射它们。命令名称可能匹配实体 方法 ,但它们的内容不会自动映射到域模型字段。

In case of using MVC framework what should be the input of my controller actions? Should it be a command, or should I create command inside my action implementation and send it?

我会说两者都是合法且适用的,除了 MVC 模型绑定偶尔出现的技术怪癖。