[英]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.