1

我有一个接口方法

  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))来调用一个需要具体类型的方法,而不知道它在编译时是哪种类型。

4

4 回答 4

9

好吧,“正确”的答案是 Handle() 应该是 ICommand 中的一个方法,因此Handle(command)您会说command.Handle().

于 2008-12-02T08:46:44.793 回答
5

转换是在编译时发出的,因此您需要在编译时知道类型。重载也是在编译时确定的——所以当你真正知道要使用的具体类型时,为时已晚。

我没有看到您实际上会通过使用委托来复制任何逻辑。或者,如果您使用反射进行此操作,则可以使用 Delegate.CreateDelegate 非常轻松地构建委托 - 您只会获得一次性能打击,之后它会非常快。有关更多信息,请参阅我关于 Delegate.CreateDelegate 的博客条目

我想我会根据我有多少方法以及它们更改的频率决定使用手工构建的字典或使用反射构建的字典。您可能会发现KeyedByTypeCollection对字典很有用。

于 2008-12-02T09:04:13.167 回答
2

你不能,你为什么要这样做?

这就是我们拥有多态性的全部原因。如果您想拥有特定于某些类型的自定义行为,那么该行为应该存在于类型本身中,并通过在基类类型中声明的函数调用。

于 2008-12-02T08:45:14.750 回答
1

我已经尝试过一种可以使用 Double Dispatch ( http://en.wikipedia.org/wiki/Double_dispatch ) 的方法,但似乎您遇到的情况是实现 ICommand 的类和实现 Execute( ) 可以在运行时变化(或者,至少在编译和运行时之间,这本质上是相同的),所以我能看到的唯一解决方案是使用 Jon Skeet 提出的字典。

于 2008-12-02T15:29:12.267 回答