在我目前正在构建的系统中,我使用命令模式来执行所有可能的操作。我选择了 CommandMessage 和 CommandHandler 方法,将逻辑与数据分开。这目前工作正常,但我遇到了一个问题 - 验证。
我如何实际验证命令是否可以执行?
现在我CanExecute(ICommandExecutionContext context)
对每个命令都有一个,让它负责确定它是否可以执行。然后在每个命令中对AICommandExecutionContext
进行类型检查,以查看它是否属于正确的上下文类型,然后检查信息是否使命令在该上下文中可执行。
一切都被包装在一个ICommandService
可以根据它们的名称、上下文和消息验证和执行命令的容器中。除此之外,它还发布有关命令执行的事件,并执行权限检查。
问题源于 UI(一个 ASP.NET MVC 3 应用程序)。我只想在每个视图中显示有效的命令,但我没有想出一个我真正喜欢的解决方案。目前我的控制器询问命令服务,一个命令是否可以执行,给定一个具体的上下文,如下所示:
var executionContext = new SystemCommandExecutionContext("SignInCommand", CurrentPrincial);
var canExecute = _commandService.CanExecute(executionContext);
/* Handle the result to enable or disable the action link */
对于适用于具体域对象的其他类型的命令,我使用相同的命令服务方法,但在不同的上下文中传递域对象 ID,如下所示:
[HttpPost, Authorize, ValidateAntiForgeryToken /* etc. */]
public ActionResult Delete(Guid id)
{
/* Note the additional object id in the context */
var executionContext = new EntityCommandExecutionContext("DeletePersonCommand", CurrentPrincipal, id);
var canExecute = _commandService.CanExecute(executionContext);
if(canExecute)
{
var message = new DeletePersonCommandMessage(id);
var isValid = _commandService.IsValid(executionContext, message);
if(isValid)
{
var result = _commandService.Execute(executionContext, message);
/* More logic here... Not very DRY :( */
}
}
}
我想上面的内容现在还可以,虽然不是很干。但我想要完成的是根据 CanExecute 的结果禁用操作链接。
我怎样才能做到这一点?
我决定对每个视图上的所有命令链接进行“硬编码”,因此我不必传递命令名称的集合等 - 这条路径太难了(除非有人有一个聪明的主意;)
我当前的堆栈包括 NHibernate、Castle Windsor、ASP.NET MVC 3、AutoMapper。