如何让委托引用特定版本的方法?

时间:2010-11-13 16:42:46

标签: c# delegates override

我想创建一个调用特定实例方法的委托,遗憾的是,如果该方法是虚拟的,那么将调用继承类的方法的覆盖而不是基本版本。

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

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

如果代码中的其他地方我有以下内容::

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

此程序的输出为Child。我真的很喜欢Base。我已经尝试了表达式树的相同的东西,我得到相同的结果,因为IL发出使用callvirt方法。用Reflection.Emit确实是这样做的唯一方法吗?

我问的原因是我使用类型构建器来覆盖类的行为。如果我自己编写方法,我可以去base.Method()或其他什么,但是,某些方法行为只能在运行时动态确定,因为考虑到许多可能的情况会非常繁琐。

由于我在运行时创建了一个派生自Base的类,如果我尝试在Method()重载内部调用Method(),我会使它导致无限递归和堆栈溢出异常。 (不太好)。

这是一个AOP样式项目,我在运行时向方法添加一些逻辑。我使用属性标记方法,然后我有一个类型构建器,使用CompileToMethod(methodbuilder) http://msdn.microsoft.com/en-us/library/dd728224.aspx创建methodBuilders,为表达式树提供方法构建器的主体, 这比反射更简单。因为逻辑是非平凡的,我正在添加。我的目标是让工厂吐出一个新的类,每当我调用Method()时,它会在最终调用基础实现之前先做一些逻辑。

4 个答案:

答案 0 :(得分:1)

也许您可以使用这样的解决方法:

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

现在,您可以创建代表MethodImpl的代理。

答案 1 :(得分:1)

是的,Reflection.Emit是.NET框架提供的实现方法重载的唯一方法。由于在重载方法时不使用其他API,因此它们不提供链接到基本实现的任何方法。

答案 2 :(得分:0)

假设在这里发生了什么?

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!

你试图打败虚拟方法的观点。为什么呢?

答案 3 :(得分:0)

由于Reflection.Emit是构建整个方法的一种困难方法,我建议使用Reflection.Emit创建私有方法,仅用于调用base方法。然后,您可以从Expression s。

中引用这些方法