使用reflection来调用重写的基本方法

如何使用reflection调用被派生类重写的基本方法?

class Base { public virtual void Foo() { Console.WriteLine("Base"); } } class Derived : Base { public override void Foo() { Console.WriteLine("Derived"); } } public static void Main() { Derived d = new Derived(); typeof(Base).GetMethod("Foo").Invoke(d, null); Console.ReadLine(); } 

此代码始终显示“派生”…

你不能这样做,即使是用reflection。 C#中的多态性实际上保证Derived.Foo()将始终被调用,即使在Derived的实例上也会被调用回其基类。

Derived实例调用Base.Foo()的唯一方法是显式地使它可以从Derived类访问:

 class Derived : Base { public override void Foo() { Console.WriteLine("Derived"); } public void BaseFoo() { base.Foo(); } } 

即使当前的答案已经被接受,但实际上可以通过使用这样的动态方法来更改原始类:

  static void Main(string[] args) { Derived foo = new Derived(); foo.Foo(); MethodInfo method = typeof(Base).GetMethod("Foo"); DynamicMethod dm = new DynamicMethod("BaseFoo", null, new Type[] { typeof(Derived) }, typeof(Derived)); ILGenerator gen = dm.GetILGenerator(); gen.Emit(OpCodes.Ldarg_1); gen.Emit(OpCodes.Call, method); gen.Emit(OpCodes.Ret); var BaseFoo = (Action)dm.CreateDelegate(typeof(Action)); BaseFoo(foo); Console.ReadKey(); } 

你可以看到它仍然相对简单

经过很长一段时间,我终于找到了比DynamicMethod更好的解决方案:

 class CallOverride { public static void Test() { var obj = new Override(); var method = typeof(object).GetMethod("ToString"); var ftn = method.MethodHandle.GetFunctionPointer(); var func = (Func)Activator.CreateInstance(typeof(Func), obj, ftn); Console.WriteLine(func()); } } class Override { public override string ToString() { return "Nope"; } } 

此解决方案使用委托的标准构造函数签名:

 public Delegate(object target, IntPtr ftn) 

其中target是目标实例,ftn是函数指针。 它使用base方法的函数指针直接调用它,因此委托将指向实际的基本方法,而不是重写的方法。

reflection允许您查看对象d具有“Foo”方法并且还可以调用它。

然而,这个方法是一个虚方法 ,这就是你通过Derived类获得该方法的实现的原因,因为这就是d(除了也可以转换为Base)。

没有[直接]方法从Derived对象调用Base的虚方法。
如Frederic Hamidi所示,Base类的方法可以通过Derived类(在不同的名称下)公开,但是它并没有真正调用Base的方法,它正在调用Derived类的方法,该方法恰好调用Base的方法。

虽然这种方法让Derived类为Base类的方法提供了“代理”,但最终会按照你的要求执行,但这样做可能是个坏主意:对象模型的设计可能存在缺陷:这将是一个相当奇怪的用例……

您所看到的是设计中的多态行为。 覆盖虚方法时,在重写的类上调用该方法将从VMT调用后代类的实现。

你的用例是什么,说实话,这有点像设计问题。

也许Kii正在寻找这样的东西

 class Base { public virtual void Foo() { Console.WriteLine("Base"); } } class Derived : Base { // Change virtual with new // public override void Foo() { Console.WriteLine("Derived"); } public new void Foo() { Console.WriteLine("Derived"); } } static void Main(string[] args) { Derived d = new Derived(); d.Foo();// Output: Derived typeof(Base).GetMethod("Foo").Invoke(d, null);// Output: Base // Or you can cast ((Base)d).Foo();// Output: base Console.ReadLine(); } 
 Base b = (Base)d; Console.WriteLine(b.GetType()); //output:Derived 

1)施法不能改变它的类类型。

 class Derived : Base { public override void Foo() { Console.WriteLine("Derived"); } public Base getBase() { return base; //compiler invalid } } 

2)上面的内容无效,因为您在创建Derived对象实例时从未创建过任何Base对象实例。 您创建了从Base classinheritance的Derived class实例对象。 希望,这解释了为什么你不能用派生对象调用基函数