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.
}
How can I get to bar inside the Zap method?
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
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.
EDIT
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With