I had the same problem, but somewhat more complex, and Darin Dimitrov’s answer gave me a good start. I’ll post my results here, despite the fact that this is an “old” question .
Case 1: The root object is an instance member
this.textBox.Text // where 'this' has type 'Form'
… is equivalent to the following expression tree:
. +====================+
. | MemberExpression |
. +====================+
# | |
# .Expression | | .Member
# v v
. +------------------+ +------------+
. | MemberExpression | | MemberInfo |
. +------------------+ +------------+
# | | .Name = "Text"
# .Expression | | .Member .MemberType = Property
# v v
. +--------------------+ +------------+
. | ConstantExpression | | MemberInfo |
. +--------------------+ +------------+
# .Value = this .Name = "textBox"
# .Type = typeof(Form) .MemberType = Field
The only place in this expression tree where you actually get an object reference is from the ConstantExpression
: it allows you to get a reference to this
. The basic idea to get any object reference in this tree is thus as follows:
-
Descend into the expression tree along the
.Expression
axes until you reach aConstantExpression
node. -
Grab that node’s
.Value
property. This is the root object reference (ie.this
in the above example). -
Using reflection and the
MemberInfo
nodes from the expression tree, get object references and work your way back “up” the expression tree.
Here’s some code that demonstrates this:
Expression expr = ...; // <-- initially set to the expression tree's root
var memberInfos = new Stack<MemberInfo>();
// "descend" toward's the root object reference:
while (expr is MemberExpression)
{
var memberExpr = expr as MemberExpression;
memberInfos.Push(memberExpr.Member);
expr = memberExpr.Expression
}
// fetch the root object reference:
var constExpr = expr as ConstantExpression;
var objReference = constExpr.Value;
// "ascend" back whence we came from and resolve object references along the way:
while (memberInfos.Count > 0) // or some other break condition
{
var mi = memberInfos.Pop();
if (mi.MemberType == MemberTypes.Property)
{
objReference = objReference.GetType()
.GetProperty(mi.Name)
.GetValue(objReference, null);
}
else if (mi.MemberType == MemberTypes.Field)
{
objReference = objReference.GetType()
.GetField(mi.Name)
.GetValue(objReference);
}
}
Case 2: The root object is a static class member
Form.textBox.Text // where 'textBox' is a static member of type 'Form'
… results in a different expression tree. Note to the null reference at the lower left:
. +====================+
. | MemberExpression |
. +====================+
# | |
# .Expression | | .Member
# v v
. +------------------+ +------------+
. | MemberExpression | | MemberInfo |
. +------------------+ +------------+
# | | .Name = "Text"
# .Expression | | .Member .MemberType = Property
# v v
. null +------------+
. | MemberInfo |
. +------------+
# .Name = "textBox"
# .MemberType = Field
# .DeclaringType = typeof(Form)
Here, you cannot stop the “descend” phase by waiting for a ConstantExpression
. Instead, you stop descending when you reach a null reference. Next, you retrieve the root object reference as follows:
var mi = memberInfos.Pop();
objReference = mi.DeclaringType
.GetField(member.Name, BindingFlags.Static) // or .GetProperty!
.GetValue(null);
The “ascend” phase from there onwards is the same as before.
There are certainly more cases (such as named parameters as the root object), but I hope that by now, I’ve got the basic idea across, so I’ll cut off here.