Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to invoke (non virtually) the original implementation of a virtual method?

Tags:

c#

.net

I have the following situation:

In a 3rd party library (can not be modified):

class A { public virtual void M() {} }

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

In my own code:

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

From C's implementation of method M I want to call A's (but not B's!!). Can I?

Any tricks accepted, reflection included. I tried reflection already, but using the MethodInfo that I get from typeof(A) still generates a virtual call (calling C's implementation with subsequent stack overflow).

Deriving C from A is out of the question due to the complexity of reimplementing B.

like image 654
Mau Avatar asked Jul 31 '10 12:07

Mau


2 Answers

you can generate dynamic method to make proxy that use Call (not CallVirt) instruction

        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);
like image 178
desco Avatar answered Nov 05 '22 16:11

desco


In my previous answer I missed the fact that A and B are in an external library and cannot be modified. In that case, I would suggest a different approach. Basically, if the design flaw is in B, you can’t use B. Subclass from A instead.

The unfortunate consequence of this, of course, is that you may need to reimplement some or all of the functionality in B. You may be able to copy the code from Reflector if necessary. I realise that this sounds undesirable, but I still think it is preferable to using unmodifiable code that has a known issue that causes you problems.

like image 25
Timwi Avatar answered Nov 05 '22 17:11

Timwi