简体   繁体   English

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

[英]How can I make a delegate refer to a specific version of a method?

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 . 该程序的输出为Child I'd really like it to be Base . 我真的很想成为Base I've tried the same thing with expression trees and I get the same result, as the IL emitted uses the callvirt method. 我已经对表达式树进行了相同的尝试,并且得到了相同的结果,因为发出的IL使用callvirt方法。 Is the only way to do something like this really with Reflection.Emit ? 使用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. 如果我自己编写方法,则可以使用base.Method()或其他方法,但是某些方法的行为只能在运行时动态确定,因为考虑到许多可能的情况将非常繁琐。

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. 由于我正在创建一个在运行时从Base派生的类,因此,如果我尝试在Method()重载内调用Method() ,我将导致无限递归和堆栈溢出异常。 (not so good). (不太好)。

This is for an AOP style project where I'm adding some logic to the methods at runtime. 这是针对AOP风格的项目的,我在运行时向方法中添加了一些逻辑。 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. 我用属性标记方法,然后有一个类型生成器,该类型生成器使用CompileToMethod(methodbuilder) http://msdn.microsoft.com/zh-cn/library/dd728224创建一个使用表达式树为methodbuilder的主体提供方法的methodBuilders 。 aspx ,这比Reflection.emit容易很多,因为我要添加的逻辑很简单。 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. 我们的目标是让我的工厂抛出一个新类,每当我调用Method()它都会先执行一些逻辑后才最终调用基本实现。

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 . 现在,您可以创建代表MethodImpl的委托。

Yes, Reflection.Emit is the only way provided by the .NET framework to implement method overloads. 是的, Reflection.Emit是.NET框架提供的唯一实现方法重载的方法。 Since the other APIs aren't used when overloading methods, they don't provide any way to chain to the base implementation. 由于重载方法时不使用其他API,因此它们不提供任何链接到基本实现的方法。

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? 为什么?

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. 由于Reflection.Emit是构建整个方法的一种困难方法,因此我建议使用Reflection.Emit创建专用于调用base方法的私有方法。 Then you can refer to those methods from your Expression s. 然后,您可以从Expression引用这些方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使对象成为窗口的委托? - How can I make an object a delegate of a window? 如何使方法匹配WinRT线程的委托&#39;WorkItemHandler&#39;? - How do I make a method match the delegate 'WorkItemHandler' for WinRT threading? 如何让我的字典参考列表 <T> 值? - How can I make my dictionary refer to List<T> values? 如何在匿名委托中调用异步方法? - How can I call an async method inside an anonymous delegate? 如何使用反射调用具有委托参数的方法? - How can I call method that has a delegate parameter using reflection? 为什么委托在静态方法中使用时不能引用非静态方法? - Why can't a delegate refer to a non-static method when used in a static method? 如何确保只能从特定的类调用类的方法? - How can I make sure that a method of class can be called from a specific class only? 如何将C#中反射获取的方法传递给接受该方法作为委托的方法? - How can I pass a method acquired by reflection in C# to a method that accepts the method as a delegate? 无法分配委派具有较少特定参数类型的匿名方法 - Can’t assign to delegate an anonymous method with less specific parameter type 如何将方法名称传递给另一个方法并通过委托变量调用它? - How can I pass a method name to another method and call it via a delegate variable?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM