查询和命令在这里是否继续被认为是分开的?
是的,通常您会触发命令,如果您需要在执行此操作后更新 UI,您将执行查询以获取新信息。举个例子就清楚了。
假设您要为某个区域分配一个特定的警卫。该命令(仅是DTO)需要的唯一信息是警卫的Id 和区域的Id。关联的CommandHandler 将执行所有任务来处理这个问题,例如将那个守卫从另一个区域移除,将他列为不可用等。
现在您的 UI 想要显示更改。 UI 可能有某种包含所有警卫及其分配区域的列表。此列表将由单个GetActiveGuardsAndAreaQuery 填充,它将返回List<GuardWithAreaInformationDto>。这个DTO 可以包含所有警卫的各种信息。从命令返回此信息并不是完全分离关注点,因为原子命令处理可以很好地用于类似但略有不同的 UI,这将需要对 UI 信息进行稍微不同的更新。
例如登录尝试。这是查询还是命令?
IMO 登录尝试都不是。这是一个横切关注点,数据隐藏在安全连接后面的实现细节。然而,应用程序不应该关心这个细节。考虑将应用程序与另一个客户一起使用,您可以在其中托管 WebApi 服务和Active Directory 域,您可以在其中使用Windows Authentication。在这种情况下,用户只需登录到他的机器,安全性由客户端和服务器操作系统在通信时处理。
对于您所指的模式,可以使用AuthenticateToWebApiServiceCommandHandlerDecorator 很好地完成此操作,通过以模式形式询问用户,从配置文件中读取它,或随便。
可以通过执行您的应用程序始终需要的一种标准Query(例如CheckIfUpdateIsAvailableQuery)来检查凭据是否有效。如果查询成功,则登录尝试成功,否则失败。
如果命令处理程序返回 void,你将如何告诉演示者用户创建请求是否成功?
虽然void 似乎没有返回任何东西,但这并不是真的。因为如果它没有因某些异常而失败(带有明确的信息,出了什么问题!)它一定是成功的。
在提到的博客文章的follow up 中,@dotnetjunkie 描述了一种从命令返回信息的方法,但请注意帖子顶部添加的评论。
总而言之,从失败的命令中抛出明确的异常。您可以添加一个额外的抽象客户端层来很好地处理这个问题。您可以注入IPromptableCommandHandler,而不是将命令处理程序直接注入到不同的演示者中,它在编译时只有一个开放的通用实现:
public interface IPromptableCommandHandler<TCommand>
{
void Handle(TCommand command, Action succesAction);
}
public class PromptableCommandHandler<TCommand> : IPromptableCommandHandler<TCommand>
{
private readonly ICommandHandler<TCommand> commandHandler;
public PromptableCommandHandler(ICommandHandler<TCommand> commandHandler)
{
this.commandHandler = commandHandler;
}
public void Handle(TCommand command, Action succesAction)
{
try
{
this.commandHandler.Handle(command);
succesAction.Invoke();
}
catch (Exception)
{
MessageBox.Show("An error occured, please try again.");
// possible other actions like logging
}
}
}
// use as:
public void SetGuardActive(Guid guardId)
{
this.promptableCommandHandler.Handle(new SetGuardActiveCommand(guardId),() =>
this.RefreshGuardsList());
}
归根结底,对于任何给定的 UI 任务(比如用户创建请求),您最终是否会拥有一个基于 winforms 客户端的查询/命令,以及一个 web api 服务版本的处理该请求的命令/查询?
不!
客户端您应该创建一个单独的开放通用CommandHandlerProxy,其唯一任务是将命令 dto 传递给 WebApi 服务。
对于服务端架构,您应该阅读另一篇后续文章:Writing Highly Maintainable WCF Services,它描述了一个服务器端架构,可以很好地处理这个问题。链接的项目还包含 WebApi 的实现!