在C#中,如何在不知道它的类型的情况下向下转换以前上传的对象?

时间:2008-12-02 08:39:52

标签: c# .net inheritance casting

我有一个界面方法

  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 个答案:

答案 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所倡导的字典。