How can I get a delegate to reference a specific version of a method?

I would like to make a delegate that calls a special instance method, unfortunately it seems that if this method is virtual, instead of the base version method, a method override for the inherited class will be called.

public class Base{ public virtual void Method(){ Console.WriteLine("Base"); } } public class Child : Base{ public override void Method(){ Console.WriteLine("Child"); } } 

If somewhere else in the code there is the following:

 var action = Delegate.CreateDelegate(typeof(Action<Base>), typeof(Base).GetMethod("Method")) as Action<Base>; action(new Child()); 

The output of this program is Child . I would really like it to be Base . I tried the same with expression trees, and I get the same result as the emitted IL uses the callvirt method. The only way to do something like this with Reflection.Emit ?

I request that I use a type builder to override class behavior. If I wrote a method myself, I could just go to base.Method() or something else, but some of the behavior methods can be determined dynamically only at runtime, since taking into account many possible cases will be very tedious.

Since I am creating a class derived from Base at runtime, if I try to call Method() inside the Method() overload that I am doing, this leads to endless recursion and exceptions. (not very good).

This is for an AOP style project where I add some logic to the methods at runtime. I tag methods with attributes, then I have a type builder that creates methodBuilders that feed the body of the method constructor using the expression tree using CompileToMethod(methodbuilder) http://msdn.microsoft.com/en-us/library/dd728224 .aspx , This is a ton lighter than reflection.emit, because the logic is nontrivial, which I add. The goal is that I have a factory, spits out a new class, which, when I call Method() , first executes some logic before ultimately invoking the base implementation.

+4
source share
4 answers

Yes, Reflection.Emit is the only way provided by the .NET platform to implement method overloads. Because other APIs are not used during overloading, they do not provide any way to bind to the underlying implementation.

+1
source

Perhaps you can use a workaround like this:

 public class Base{ public virtual void Method(){ MethodImpl(); } public void MethodImpl(){ Console.WriteLine("Base"); } } public class Child : Base{ public override void Method(){ Console.WriteLine("Child"); } } 

Now you can create a delegate representing MethodImpl .

+1
source

What is going to happen here?

 class Base { public abstract void Method(); } class Child { public override void Method() { Console.WriteLine("Child.Method"); } } Action<Base> magicalAction = // defined somehow magicalAction(new Child()); // aiya! 

You are trying to defeat the point of virtual methods. Why?

0
source

Since Reflection.Emit is such a complex way to build an entire method, I would recommend using Reflection.Emit to create private methods only to call base methods. You can then access these methods from Expression s.

0
source

All Articles