我有一个界面方法
public void Execute(ICommand command);
需要将已知的ICommand
子类型传递给适当的Handle(SpecificCommand command)
方法实现,并对未知类型进行一些通用处理。我正在寻找一种通用(即不需要巨大的开关)方法,类似于
Handle(command as command.GetType()); // this obviously does not compile
我知道我可以以某种方式注册处理程序,例如将它们作为代理存储在字典中,但这仍然需要复制处理逻辑(一次在特定的Handle(...)
方法签名中,一次在委托重新注册中)。如果我通过使用反射检查我的类填充字典(寻找Handle(XXX command)
方法),我将获得性能损失。
总结一下:我如何向下转换一个对象(通过调用Execute(ICommand command)
来升级)来调用一个需要具体类型的方法,而不知道它在编译时是哪种类型。
答案 0 :(得分:9)
嗯,“正确”的答案是Handle()应该是ICommand中的一个方法,所以你不是Handle(command)
,而是command.Handle()
。
答案 1 :(得分:5)
转换是在编译时发出的,因此您需要在编译时知道类型。重载也是在编译时确定的 - 所以当你真正知道要使用的具体类型时,为时已晚。
我没有看到您实际上是通过使用委托来复制任何逻辑。或者,如果你使用反射进行,你可以使用Delegate.CreateDelegate非常轻松地构建委托 - 你只会获得一次性能,之后它会非常快。有关详细信息,请参阅我的blog entry about Delegate.CreateDelegate。
我想我决定使用一个手工制作的字典,或者根据我有多少方法以及它们改变的频率使用反射构建的字典。您可能会发现KeyedByTypeCollection对字典很有用。
答案 2 :(得分:2)
你不能,为什么要这样?
这就是我们有多态性的全部原因。如果您希望具有特定于某些类型的自定义行为,那么该行为应该存在于类型本身中,并通过在基类类型中声明的函数来调用。
答案 3 :(得分:1)
我尝试过使用Double Dispatch(http://en.wikipedia.org/wiki/Double_dispatch)的方法,但似乎你有一种情况,实现ICommand的类和执行Execute()的类在运行时会有所不同-time(或者,至少在编译和运行时之间,这基本上是相同的事情),所以我能看到它的唯一解决方案是使用Jon Skeet所倡导的字典。