温莎城堡/ DI和对象模型

Hol*_*ing 5 command castle-windsor castle

我现在使用温莎城堡已经有一段时间了.它非常适用于数据位于数据库等中的环境,其中存储库模式或单元工作模式运行良好.

现在我确实有不同的情况:我有一个复杂的对象模型,由很多单个PONO组装.COM对环境的影响很大,使其更加明确:Excel,Word PIO被大量使用.

我使用命令模式,我实现了ICommandHandler,就像这里描述的那样,但有一点不同.因为我想将命令汇编到命令列表以在运行中调用它们而不知道所描述的一般命令模式旁边的任何内容,所以在调用execute方法时不会引入上下文.所以界面看起来像这样:

    public interface ICommand
    {
        void Execute();
        bool CanExecute();
    }
Run Code Online (Sandbox Code Playgroud)

使用该接口执行命令是有效且易于理解的.另一方面,使用ctor引入上下文是一个问题,因为必须明确地调用Container以例如添加ctor参数.

所以我实际上有两个问题:

  1. 是否有可能注入一个 - 让它称之为上下文,对象模型的一部分 - 由温莎城堡自动调用,而不是明确地调用容器?
  2. 如何使用DI从命令模式参与?任何想法如何通过遵循此处描述的RRR规则来完成能够定义任务/操作列表等?

Mar*_*ius 4

基础设施:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

登记:

        container.Register(Component.For<ICommandExecutor>().ImplementedBy<CommandExecutor>()
            .Interceptors<ExceptionToCommandResult>()
            .Interceptors<ExceptionLogger>()
            .Interceptors<HandleWhenDeadlockVictim>()
            .Interceptors<RetryCommand>()
            .Interceptors<ContainerScopeWrapper>()
            .Interceptors<TransactionWrapper>()
            .Interceptors<SameNhibernateSessionAndTransactionWrapper>());
Run Code Online (Sandbox Code Playgroud)

例子:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

所有 AOP 的东西都处理事务等等。命令执行器是无状态的单例,处理程序指定它们的不同需求。命令执行器只是与基础设施和域无关,因此请将其放置在域之外您喜欢的位置。这是一个大系统上的生产代码,很有魅力。