如何使用 Expression.Bind / Expression.MemberBind 绑定嵌套成员?
How to bind nested members using Expression.Bind / Expression.MemberBind?
测试类
public class Foo
{
public Bar Bar { get; set; }
}
public class Bar
{
public string Baz { get; set; }
}
public class BindFoo
{
public string BarBaz { get; set; }
}
片段
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();
嵌套 属性 时,在 expression.Compile()
处抛出 'x' 未定义错误。如何绑定嵌套的 属性 Bar.Baz?
上面代码中构建的表达式是x => new BindFoo() {BarBaz = x.Bar.Baz}
,这是我想要的,但我认为x.Bar.Baz
没有被正确绑定。
问题与Bind
和嵌套成员无关,而是动态创建的lambda表达式的参数。
参数按实例绑定,而不是按名称绑定。这里
Expression<Func<Foo, object>> baz = x => x.Bar.Baz;
var param = Expression.Parameter(typeof(Foo), "x");
您定义了一个新参数,但随后尝试使用绑定到它自己的参数的 baz.Body
。
解决方法是使用原参数
Expression<Func<Foo, object>> baz = x => x.Bar.Baz;
var param = baz.Parameters[0];
或使用表达式 visitor 将 baz.Parameters[0]
替换为新参数。
测试类
public class Foo
{
public Bar Bar { get; set; }
}
public class Bar
{
public string Baz { get; set; }
}
public class BindFoo
{
public string BarBaz { get; set; }
}
片段
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();
嵌套 属性 时,在 expression.Compile()
处抛出 'x' 未定义错误。如何绑定嵌套的 属性 Bar.Baz?
上面代码中构建的表达式是x => new BindFoo() {BarBaz = x.Bar.Baz}
,这是我想要的,但我认为x.Bar.Baz
没有被正确绑定。
问题与Bind
和嵌套成员无关,而是动态创建的lambda表达式的参数。
参数按实例绑定,而不是按名称绑定。这里
Expression<Func<Foo, object>> baz = x => x.Bar.Baz;
var param = Expression.Parameter(typeof(Foo), "x");
您定义了一个新参数,但随后尝试使用绑定到它自己的参数的 baz.Body
。
解决方法是使用原参数
Expression<Func<Foo, object>> baz = x => x.Bar.Baz;
var param = baz.Parameters[0];
或使用表达式 visitor 将 baz.Parameters[0]
替换为新参数。