我必须设计一个 Command/CommandHandler 模块,并且正在为设计的细节而苦苦挣扎。

我创建了一个(空)界面:

public interface ICommand {}

由各种命令实现,

例如
public interface TestCommand : ICommand {}

一个(或多个)CommandHandlers 可以注册 ICommand 的特定实现。为了避免不断的类型转换,我建立了一个接口(interface):
public interface ICommandHandler<in TCommand>
       where TCommand : ICommand
{
    void Handle(TCommand command);
}

到目前为止一切顺利......命令调度系统是令人不安的东西:命令处理程序应该由 Autofac(或任何其他 DI 系统)注入(inject),例如:
public CommandDispatcher (IEnumerable<ICommandHandler<ICommand>> commandHandlers)

如您所见,这是不可能的。 ICommandHandler<CommandType1>ICommandHandler<CommandType2> 不是从 ICommandHandler<ICommand> 派生的,因此不能放入同一个 IEnumerable。

任何建议如何以无问题的方式设计它?

最佳答案

通常,您会在调用它们之前解决它们。例如,在 Autofac

class CommandDispatcher
{
    private readonly Autofac.IComponentContext context; // inject this

    public void Dispatch<TCommand>(TCommand command)
    {
        var handlers = context.Resolve<IEnumerable<ICommandHandler<TCommand>>>();
        foreach (var handler in handlers)
        {
            handler.Handle(command);
        }
    }

    public void ReflectionDispatch(ICommand command)
    {
        Action<CommandDispatcher, ICommand> action = BuildAction(command.GetType());
        // see link below for an idea of how to implement BuildAction

        action(this, command);
    }
}

如果您需要将方法签名更改为 Dispatch(ICommand command) ,请参阅 this answer 。您应该能够根据您的情况进行调整。

关于C#泛型/ICommandHandler/ICommand设计,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16820038/

10-11 22:43