我正在尝试合并expr1
和expr2
来制作Expression<Func<float>>
:
var expr1 = (Expression<Func<ColorComponent>>)(() => _modelRgb.R);
var expr2 = (Expression<Func<ColorComponent, float>>)(s => s.Value);
var expr3 = Expression.Lambda(expr1, expr2.Parameters);
虽然对expr3
的调用确实有效,但其.Body
属性无法投放为MemberExpression
。
以下是手动制作的表达式和expr3
的调试字符串,显然它们不同:
"() => (ColorPicker.ColorPickerWindow2)._modelRgb.R.Value"
"s => () => (ColorPicker.ColorPickerWindow2)._modelRgb.R"
问题是:
使expr3
成为MemberExpression
而不是LambdaExpression
的正确方法是什么?
我想要实现的目标:
我想将() => _modelRgb.R
之类的表达式传递给一个方法的ColorComponent
,在这个方法中,我想为它的一些成员构建多个表达式。
答案 0 :(得分:2)
你从根本上想要做的是组成两个表达式。 Here是一个解决方案,展示了如何做到这一点,虽然它需要一些适应性,以使第一个表达式没有参数,而不是一个参数。
改编后的Compose
方法如下所示:
public static Expression<Func<TResult>> Compose<TSource, TResult>(
this Expression<Func<TSource>> first,
Expression<Func<TSource, TResult>> second)
{
return Expression.Lambda<Func<TResult>>(
second.Body.Replace(second.Parameters[0], first.Body));
}
这将使用与链接问题相同的Replace
方法,无需任何改编:
public class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression ex)
{
if (ex == from) return to;
else return base.Visit(ex);
}
}
public static Expression Replace(this Expression ex,
Expression from,
Expression to)
{
return new ReplaceVisitor(from, to).Visit(ex);
}
通过使用上述方法推广代码,您可以确保代码在任何表达式的内容中都无论,而不是编写一个方法来假设什么可以或者可以&#t; t在任何一个表达中,或以不同的方式处理一堆不同的情况。