基础设施:
public interface ICommandHandler<in T>
{
void Handle(T command);
}
public interface ICommandExecutor
{
CommandResult ExecuteCommand(Command command);
CommandResult ExecuteCommands(Command[] commands);
}
public abstract class Command
{
}
public class CommandExecutor : ICommandExecutor
{
private readonly IWindsorContainer _kernel;
public CommandExecutor(IWindsorContainer kernel)
{
Guard.AssertNotNull(() => kernel);
_kernel = kernel;
}
public CommandResult ExecuteCommand(Command command)
{
return ExecuteInternal(command);
}
public CommandResult ExecuteCommands(Command[] commands)
{
CommandResult result = null;
foreach (Command command in commands)
{
result = ExecuteInternal(command);
if (!result.IsExecuted)
return result;
}
return result ?? CommandResult.Executed("Command executed successfully");
}
private CommandResult ExecuteInternal(Command command)
{
dynamic handler = FindHandlerForCommand(command);
try
{
handler.Handle(command as dynamic);
return CommandResult.Executed("Command executed successfully");
}
finally
{
_kernel.Release(handler);
}
}
private object FindHandlerForCommand(Command command)
{
Type handlerType = typeof (ICommandHandler<>).MakeGenericType(command.GetType());
dynamic handler = _kernel.Resolve(handlerType);
return handler;
}
}
登记:
container.Register(Component.For<ICommandExecutor>().ImplementedBy<CommandExecutor>()
.Interceptors<ExceptionToCommandResult>()
.Interceptors<ExceptionLogger>()
.Interceptors<HandleWhenDeadlockVictim>()
.Interceptors<RetryCommand>()
.Interceptors<ContainerScopeWrapper>()
.Interceptors<TransactionWrapper>()
.Interceptors<SameNhibernateSessionAndTransactionWrapper>());
例子:
public class WriteComment : Command
{
public string GameToCommentId { get; set; }
public string Comment { get; set; }
}
public class WriteCommentCommandHandler : ICommandHandler<WriteComment>
{
private readonly IGameRepository _repository;
public WriteCommentCommandHandler(IGameRepository repository)
{
Guard.AssertNotNull(() => repository);
_repository = repository;
}
public void Handle(WriteComment command)
{
var game = _repository.Get(new Guid(command.GameToCommentId));
game.WriteComment(command.Comment, DateTime.Now);
}
}
所有 AOP 的东西都处理事务等等。命令执行器是一个无状态的单例,处理程序指定它们的不同需求。命令执行器只是基础设施和域无关,所以将它放在你喜欢的域之外的地方。这是一个大系统上的生产代码,就像一个魅力。