如何调用(非虚拟)虚拟方法的原始实现?

我有以下情况:

在第三方库中(无法修改):

class A { public virtual void M() {} } class B : A { public override void M() {} } 

在我自己的代码中:

 class C : B { public override void M() {} } 

C的方法M的实现,我想调用A (但不是B的!!)。 我可以吗?

接受任何技巧,包括反思。 我已经尝试过reflection,但是使用从typeof(A)获得的MethodInfo仍然会生成一个虚拟调用(调用C的实现,后续堆栈溢出)。

由于重新实现B的复杂性,从A导出C是不可能的。

你可以生成动态方法来制作使用Call(而不是CallVirt)指令的代理

  var x = new C(); var m = typeof (A).GetMethod("M"); var dm = new DynamicMethod("proxy", typeof (void), new [] {typeof(C)}, typeof (C)); var il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, m); il.Emit(OpCodes.Ret); var action = (Action)dm.CreateDelegate(typeof (Action)); action(x); 

我担心这不可能直接以你描述的方式实现 – 虚方法的目的是使覆盖变得透明。 因此,实现此目的的唯一方法是通过解决方法。

让我尝试鞭打一个,但请注意这是一个hacky建议。 如果你真的需要在你的代码中使用这个构造,那么可能表明你的代码在其他地方有一个基本的设计缺陷,因此重构某些东西可能比填充另一个设计缺陷更令人满意。 但无论如何,这里……

 class A { public virtual void M() { m_protected(); } protected void m_protected() { /* code goes here */ } } class B { public override void M() { /* code here, possibly invoking base.M() */ } } class C { public override void M() { m_protected(); } } 

在我之前的回答中,我错过了A和B在外部库中并且无法修改的事实。 在这种情况下,我建议采用不同的方法。 基本上,如果设计缺陷在B中,则不能使用A中的B. Subclass。

当然,这样做的不幸结果是您可能需要重新实现B中的部分或全部function。如有必要,您可以从Reflector复制代码。 我意识到这听起来不合适,但我仍然认为使用具有已知问题的不可修改代码更可取。

你不能这样做。 您可能应该以不同的方式设计类层次结构,因为C从Binheritance而看起来很奇怪,而行为类似于A.

无论如何,它可能在你的情况下有意义。 然后你应该在A中制作另一个你不会覆盖的方法:

 class A { protected virtual void basicM() {} public virtual void M() { basicM(); } } class C { public override void M() { basicM(); } } 

顺便说一句,如果你像我在示例中所做的那样命名方法,那么你应该重新考虑整个事情。 如果这个层次结构是合理的, basicM可能会执行一些值得成为具有不同名称的单独方法的东西,甚至可能是公共方法。