如何调用(非虚拟)虚拟方法的原始实现?
我有以下情况:
在第三方库中(无法修改):
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
可能会执行一些值得成为具有不同名称的单独方法的东西,甚至可能是公共方法。