我必须设计一个 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/