我想用泛型编写一个命令处理器。其思想是通过单个对象(commandprocessor本身)发出命令,然后标识处理给定命令的命令处理程序。
但是,以下代码无法编译,我无法理解原因:
class GenericCommandProcessor : ICommandProcessor
{
private readonly IDictionary<Type, IList<ICommandHandler<ICommand>>> _handlers =
new Dictionary<Type, IList<ICommandHandler<ICommand>>>();
public void Register<TCommand>(ICommandHandler<TCommand> handler)
where TCommand : ICommand
{
IList<ICommandHandler<ICommand>> handlers = GetHandlers<TCommand>();
handlers.Add(handler); // <-- This doesn't compile
}
public void Process<TCommand>(TCommand command)
where TCommand : ICommand
{
IList<ICommandHandler<ICommand>> handlers = GetHandlers<TCommand>();
foreach (var commandHandler in handlers)
{
commandHandler.Handle(command);
}
}
private IList<ICommandHandler<ICommand>> GetHandlers<TCommand>()
{
Type commandType = typeof(TCommand);
IList<ICommandHandler<ICommand>> handlers;
if (!_handlers.TryGetValue(commandType, out handlers))
{
handlers = new List<ICommandHandler<ICommand>>();
_handlers.Add(commandType, handlers);
}
return handlers;
}
}
这是不编译的行:
handlers.Add(handler);
编译器返回以下错误:
cannot convert from 'GenericCommandHandlerTest.ICommandHandler<TCommand>' to 'GenericCommandHandlerTest.ICommandHandler<GenericCommandHandlerTest.ICommand>'
我希望它是这样,因为
Register()
有一个通用约束:where TCommand : ICommand
我通过从ioc(castle windsor在我的例子中是castle windsor)解析命令处理程序列表来避免这个问题,而使用注册处理程序列表字典,但是我很想理解为什么在clr级别,这段代码不能编译。我想我只是看不见树木的树林…
多谢提前。
最佳答案
把你的方法改成:
public void AddListItem(IListItem listItem)
{
_items.Add(listItem);
}
这里不需要使用泛型。
正如其他人已经说过的:即使没有更改,您的代码也会编译,所以请更新您的示例代码。
修复示例后更新:
不能将
ICommandHandler<TCommand>
类型的变量添加到IList<ICommandHandler<ICommand>>
,因为ICommandHandler<ICommand>
和ICommandHandler<TCommand>
是两种不同的类型,尽管TCommand
实现ICommand
。如果可以的话,我的第一个答案将是正确的,你不需要首先使你的方法通用。我想Covariance在这里会有帮助,但不幸的是,在这种情况下它不受支持。