我最近看到了一些代码方案,其中CommandHandler被注入ICommandExecutor以调用其他命令。所以命令中的命令。对于一些注入IQuery的QueryHandler也是如此。
public class UpdateCarDetailsCommandHandler : CommandHandler<UUpdateCarDetailsCommand>
{
private ICommandExecutor _command;
public UpdateCarDetailsCommandHandler (ICommandExecutor command)
{
_command = command;
}
public override void Execute(UpdateCarDetailsCommand command)
{
//do something with repository
_command.Execute(new CarColour())
}
}
这对我来说似乎不正确,因为ICommandExecutor将是此场景中的组合根。只是想知道人们对此的看法?
答案 0 :(得分:8)
我说你在其他命令和查询中使用命令和查询时要小心谨慎。 注意做太多的抽象。
CQRS中的S代表Segregation。这显然意味着命令应该与其他命令保持分离,并且查询应该与其他查询保持分离。但命令可以使用查询吗?一如既往,这取决于。
2009年Udi Dahan的article建议不要:
由于您的查询现在是在与主数据库不同的单独数据存储中执行的,并且不会假设所提供的数据是100%最新的,因此您可以轻松添加这些存储的更多实例而无需担心它们不包含完全相同的数据。
Dino Esposito recommends使用单独的项目:
应用CQRS意味着您将使用两个不同的中间层。一层负责处理改变系统状态的命令。另一个检索数据。您可以从主Web服务器项目创建几个类库项目 - 查询堆栈和命令堆栈 - 并引用它们。
我个人认为,您应该将这些标准命令和查询处理程序视为整体抽象。整体抽象是一种与整个交易有关的抽象;在单个事务的范围内,它不能是一个比自身更大的依赖。
需要的是相似的抽象策略对,这些抽象策略可以用横切关注点进行修饰。
E.g。
public interface IDataCommandHandler<TCommand> where TCommand : IDataCommand
{
void Handle(TCommand command);
}
public interface IDataQueryHandler<TQuery, TResult> where TQuery : IDataQuery<TResult>
{
TResult Handle(TQuery query);
}
或
public interface ICommandStrategyHandler<TCommand> where TCommand : ICommand
{
void Handle(TCommand command);
}
public interface IQueryStrategyHandler<TQuery, TResult> where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}