问题描述
关于表达式树,我是一个新手,所以我不确定如何问这个问题或使用什么术语.这是我正在尝试做的一个过于简化的版本:
I'm a newbie when it comes to expression trees, so I'm not sure how to ask this question or what terminology to use. Here's an overly-simplifed version of what I'm trying to do:
Bar bar = new Bar();
Zap(() => bar.Foo);
public static void Zap<T>(Expression<Func<T>> source)
{
// HELP HERE:
// I want to get the bar instance and call bar.Zim() or some other method.
}
如何进入Zap方法的内部?
How can I get to bar inside the Zap method?
推荐答案
由于传递给Zap
方法的表达式是一棵树,因此只需要使用表达式树访问者,然后在表达式中查找第一个ConstantExpression
.可能会按以下顺序进行:
Since the expression passed into your Zap
method is a tree, you just need to walk the tree using an Expression Tree Visitor and look for the first ConstantExpression
in the expression. It will likely be in the following sequence:
(((source.Body as MemberExpression).Expression as MemberExpression).Expression as ConstantExpression).Value
请注意,bar
实例是由闭包捕获的,闭包是作为实例的内部类实现的,该实例作为成员,这是第二个MemberExpression的来源.
Note that the bar
instance is captured by a closure, which is implemented as an internal class with the instance as a member, which is where the 2nd MemberExpression comes from.
编辑
然后,您必须像这样从生成的闭包中获取字段:
Then you have to get the field from the generated closure like so:
static void Main(string[] args)
{
var bar = new Bar();
bar.Foo = "Hello, Zap";
Zap(() => bar.Foo);
}
private class Bar
{
public String Foo { get; set; }
}
public static void Zap<T>(Expression<Func<T>> source)
{
var param = (((source.Body as MemberExpression).Expression as MemberExpression).Expression as ConstantExpression).Value;
var type = param.GetType();
// Note that the C# compiler creates the field of the closure class
// with the name of local variable that was captured in Main()
var field = type.GetField("bar");
var bar = field.GetValue(param) as Bar;
Debug.Assert(bar != null);
Console.WriteLine(bar.Foo);
}
这篇关于表达式树-如何获得声明实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!