4

I'd like to make a delegate that invokes a specific instance method, unfortunately, it seems that if the method is virtual, the override of the method for the inheriting class will be invoked rather than the base version.

    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 I have 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'd really like it to be Base. I've tried the same thing with expression trees and I get the same result, as the IL emitted uses the callvirt method. Is the only way to do something like this really with Reflection.Emit?

The reason I ask is that I am using a type builder to override behavior of a class. If I were to write the method myself, I could just go base.Method() or whatever, but, some of the method behavior can only be determined dynamically at runtime, as accounting for the many possible cases would be very tedious.

Since i'm creating a class that derives from Base at runtime, if I try to invoke Method() inside the Method() overload I'm making it leads to infinite recursion and stack overflow exceptions. (not so good).

This is for an AOP style project where I'm adding some logic to the methods at runtime. I tag the methods with attributes, I then have a type builder that create methodBuilders feeding the body of the methodbuilder with an expression tree using the CompileToMethod(methodbuilder) http://msdn.microsoft.com/en-us/library/dd728224.aspx, This is a ton easier than reflection.emit, as the logic is non-trivial that I am adding. The goal is than I have a factory spit out a new class that whenever I call Method() it does some logic first before ultimately calling the base implementation.

Michael B
  • 7,512
  • 3
  • 31
  • 57
  • 7
    Why do people fight the type system? – ChaosPandion Nov 13 '10 at 16:45
  • I'm generating a type at runtime. I need a way to invoke methods on class I'm deriving from, I don't want to use `Reflection.Emit` if I can help it? – Michael B Nov 13 '10 at 17:00
  • Again, what if the method is abstract? And if you want to call the base method, why are you overriding them? – jason Nov 13 '10 at 17:02
  • How are you generating a type without using `Reflection.Emit`? – Ben Voigt Nov 13 '10 at 17:03
  • I'm using Expression trees ability to be compiled into method builders. I'm trying to use expression trees to rapidly build methods. @Jason, I choose which methods to override, if the method is abstract then its an error on my part to try to override it. Also I'm adding more logic to the method, I'm doing a form of AOP. – Michael B Nov 13 '10 at 17:30

4 Answers4

1

Maybe you can use such a workaround:

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.

Vlad
  • 35,022
  • 6
  • 77
  • 199
  • this works, but is incredibly tedious and would require me to write an underlying `MethodImpl` for all methods I plan on overriding. I can't really afford the effort to do so. – Michael B Nov 13 '10 at 17:01
  • You would actually want `MethodImpl` to be `protected` because it should only be available from the derived classes. – Gabe Nov 13 '10 at 17:14
1

Yes, Reflection.Emit is the only way provided by the .NET framework to implement method overloads. Since the other APIs aren't used when overloading methods, they don't provide any way to chain to the base implementation.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • interesting, what is the purpose of allowing me to save an expression tree to a method builder if I can't really use the method I made by the expression tree? – Michael B Nov 13 '10 at 17:03
  • Well, a `MethodBuilder` implemented using `ILGenerator` and using expression trees can call each other (anything using `MethodBuilder` is still considered part of Reflection.Emit), I think this is the point of Gabe's answer. So use each API for its strengths. – Ben Voigt Nov 14 '10 at 06:26
0

What's suppose 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're trying to defeat the point of virtual methods. Why?

jason
  • 236,483
  • 35
  • 423
  • 525
0

Since Reflection.Emit is such a difficult way to build a whole method, I would recommend using Reflection.Emit to create private methods just for calling the base methods. Then you can refer to those methods from your Expressions.

Gabe
  • 84,912
  • 12
  • 139
  • 238
  • That actually is the plan. Unfortunately, I discovered that you can't make parameters of a `TypeBuilder`, and can't call a `MethodBuilder` from an expression trees, making CompileToMethod pretty useless. I guess you can make a static method that can't be called without reflection? – Michael B Nov 15 '10 at 04:00
  • Michael: So you're saying that you can't call the helper method from your expression trees? I think you can get around that by creating an intermediate class that inherits from the base. Then once you have an actual assembly for that class, you can derive your actual class that uses expression trees. – Gabe Nov 15 '10 at 04:27