Test classes
public class Foo
{
public Bar Bar { get; set; }
}
public class Bar
{
public string Baz { get; set; }
}
public class BindFoo
{
public string BarBaz { get; set; }
}
Snippet
Expression<Func<Foo, object>> baz = x => x.Bar.Baz;
var param = Expression.Parameter(typeof(Foo), "x");
var bindings = typeof(BindFoo)
.GetProperties()
.Select(x => Expression.Bind(x, (MemberExpression)baz.Body))
.OfType<MemberBinding>()
.ToArray();
var expression = Expression.Lambda<Func<Foo, object>>(
Expression.MemberInit(
Expression.New(typeof(BindFoo).GetConstructor(Type.EmptyTypes)),
bindings),
param);
var func = expression.Compile();
Throws the 'x' not defined error at expression.Compile()
when the property is nested. How do I bind the nested property Bar.Baz?
The expression built in the code above is x => new BindFoo() {BarBaz = x.Bar.Baz}
, which is what I want but I think the x.Bar.Baz
had not been bound correctly.
The problem is not related to Bind
and nested members, but the parameter of the dynamically created lambda expression.
Parameters bind by instance, not by name. Here
Expression<Func<Foo, object>> baz = x => x.Bar.Baz;
var param = Expression.Parameter(typeof(Foo), "x");
you defined a new parameter, but then trying to use baz.Body
which is bound to it's own parameter.
The solution is to use the original parameter
Expression<Func<Foo, object>> baz = x => x.Bar.Baz;
var param = baz.Parameters[0];
or replace the baz.Parameters[0]
with the new parameter using expression visitor.