Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use reflection to invoke an overridden base method

Tags:

How to use reflection call a base method that is overridden by derived class?

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(); } 

This code always shows 'Derived'...

like image 686
Kii Avatar asked Dec 05 '10 06:12

Kii


People also ask

How do you call a base class overridden method?

Because you've typed it as a BaseClass instead of an A or a B, the baseclass is the begin point for the method calls. You might try using a generic: public class AnotherObject { public AnotherObject<T>(T someObject) where T : BaseClass { someObject. MyMethod(); //This calls the BaseClass method, unfortunately. } }

What is the use of invoke in c#?

The Invoke method searches up the control's parent chain until it finds a control or form that has a window handle if the current control's underlying window handle does not exist yet. If no appropriate handle can be found, the Invoke method will throw an exception.


2 Answers

After a long time, I finally find a better solution than 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<string>)Activator.CreateInstance(typeof(Func<string>), obj, ftn);         Console.WriteLine(func());     } }  class Override {     public override string ToString()     {         return "Nope";     } } 

This solution use the standard constructor signature of delegate:

public Delegate(object target, IntPtr ftn) 

where target is the target instance and ftn is the function pointer. It directly invoke it with the function pointer of base method, so the delegate will point to the actual base method, not the overridden method.

like image 73
Kii Avatar answered Nov 05 '22 08:11

Kii


Even though the current answer is already accepted, it's actually possible without having to change the original class by using a dynamic method like this:

    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<Derived>)dm.CreateDelegate(typeof(Action<Derived>));         BaseFoo(foo);          Console.ReadKey();     } 

as you can see it's still relatively simple to do

like image 20
Doggett Avatar answered Nov 05 '22 08:11

Doggett