Given the following code…
class Program {
static void Main(string[] args) {
Foo foo = new Foo { Bar = new Bar { Description= "Martin" }, Name = "Martin" };
DoLambdaStuff(foo, f => f.Name);
DoLambdaStuff(foo, f => f.Bar.Description);
}
static void DoLambdaStuff<TObject, TValue>(TObject obj, Expression<Func<TObject, TValue>> expression) {
// Set up and test "getter"...
Func<TObject, TValue> getValue = expression.Compile();
TValue stuff = getValue(obj);
// Set up and test "setter"...
ParameterExpression objectParameterExpression = Expression.Parameter(typeof(TObject)), valueParameterExpression = Expression.Parameter(typeof(TValue));
Expression<Action<TObject, TValue>> setValueExpression = Expression.Lambda<Action<TObject, TValue>>(
Expression.Block(
Expression.Assign(Expression.Property(objectParameterExpression, ((MemberExpression)expression.Body).Member.Name), valueParameterExpression)
), objectParameterExpression, valueParameterExpression
);
Action<TObject, TValue> setValue = setValueExpression.Compile();
setValue(obj, stuff);
}
}
class Foo {
public Bar Bar { get; set; }
public string Name { get; set; }
}
class Bar {
public string Description{ get; set; }
}
The call to DoLambdaStuff(foo, f => f.Name) works ok because I am accessing a shallow property, however the call to DoLambdaStuff(foo, f => f.Bar.Description) fails – although the creation of the getValue function works fine, the creation of the setValueExpression fails because I am attempting to access a deep property of the object.
Can anybody please help me to modify this so that I can create the setValueExpression for deep properties as well as shallow?
Thanks.
You need to take advantage of the fact that your expression.Body is already representing the property you want to set. This means you can use expression.Body as the left-hand-side in your assignment expression: