我有以下情况:
在第三方库中(无法修改):
class A { public virtual void M() {} }
class B : A { public override void M() {} }
Run Code Online (Sandbox Code Playgroud)
在我自己的代码中:
class C : B { public override void M() {} }
Run Code Online (Sandbox Code Playgroud)
从我想要调用C的方法的实现(但不是!!).我可以吗?MAB
接受任何技巧,包括反思.我已经尝试过反射,但是使用MethodInfo我得到的反射typeof(A)仍然会产生一个虚拟调用(调用C后续堆栈溢出的实现).
派生C从A是出了问题,由于重新实现的复杂性B.
des*_*sco 16
你可以生成动态方法来制作使用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<C>)dm.CreateDelegate(typeof (Action<C>));
action(x);
Run Code Online (Sandbox Code Playgroud)
很老的问题,但我最近遇到了类似的问题。德斯科的回答给出了关键的暗示。但生成的代理委托应该封装在类 C 中,可以是静态的并通过静态构造函数初始化,因此耗时的反射只需要一次。
// -- in foreign assembly
class A { public virtual void M() { Console.WriteLine("A.M"); }}
class B : A {public override void M() { Console.WriteLine("B.M"); }}
//
// -- in own assembly
class C : B
{
private static Action<C> call_A_M;
public override void M() {
call_A_M(this);
Console.WriteLine("C.M");
}
static C()
{
var m = typeof(A).GetMethod("M");
var dm = new DynamicMethod("", 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);
call_A_M = (Action<C>)dm.CreateDelegate(typeof(Action<C>));
}
}
Run Code Online (Sandbox Code Playgroud)
但正如 Dan Bryant 已经提到的:永远不要在生产代码中使用这种肮脏的技巧。