合并两个相同类型的表达式(没有布尔值)
Merge two expressions of same type (without bool)
我有一个采用表达式 Expression<Func<TFoo, string>> exp
的方法。
我可以像这样传递单个表达式
MyMethod(o => o.SomeStringProperty);
但现在我想合并表达式(来自两个字符串属性)并传入此方法
我找到的每个其他示例都是 Expression<Func<Foo, bool>>
。
我试过了
Expression<Func<TFoo, string>> fn1 = x => x.SomeStringProperty1;
Expression<Func<TFoo, string>> fn2 = x => x.SomeStringProperty2;
var body = Expression.Coalesce(fn1.Body, fn2.Body);
var lambda = Expression.Lambda<Func<TFoo, string>>(body, fn1.Parameters[0]);
但几乎每个 Expression 函数都会抛出异常。这个组合怎么做?
组合 lambda 表达式时,应确保它们绑定到结果表达式中使用的同一个参数 instances。
可以通过两种方式实现。
首先是使用Expression.Invoke
方法:
var body = Expression.Coalesce(fn1.Body, Expression.Invoke(fn2, fn1.Parameters[0]));
var lambda = Expression.Lambda<Func<TFoo, string>>(body, fn1.Parameters[0]);
这是最简单的方法,但会为 Entity Framework 和不支持调用表达式的类似方法创建不受支持的表达式。
第二种方法使用简单的参数替换器帮助程序将第二个 lambda 表达式主体重新绑定到第一个 lambda 表达式参数:
public static class ExpressionUtils
{
public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
{
return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
}
class ParameterReplacer : ExpressionVisitor
{
public ParameterExpression Source;
public Expression Target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == Source ? Target : base.VisitParameter(node);
}
}
}
像这样
var body = Expression.Coalesce(fn1.Body,
fn2.Body.ReplaceParameter(fn2.Parameters[0], fn1.Parameters[0]));
var lambda = Expression.Lambda<Func<TFoo, string>>(body, fn1.Parameters[0]);
我有一个采用表达式 Expression<Func<TFoo, string>> exp
的方法。
我可以像这样传递单个表达式
MyMethod(o => o.SomeStringProperty);
但现在我想合并表达式(来自两个字符串属性)并传入此方法
我找到的每个其他示例都是 Expression<Func<Foo, bool>>
。
我试过了
Expression<Func<TFoo, string>> fn1 = x => x.SomeStringProperty1;
Expression<Func<TFoo, string>> fn2 = x => x.SomeStringProperty2;
var body = Expression.Coalesce(fn1.Body, fn2.Body);
var lambda = Expression.Lambda<Func<TFoo, string>>(body, fn1.Parameters[0]);
但几乎每个 Expression 函数都会抛出异常。这个组合怎么做?
组合 lambda 表达式时,应确保它们绑定到结果表达式中使用的同一个参数 instances。
可以通过两种方式实现。
首先是使用Expression.Invoke
方法:
var body = Expression.Coalesce(fn1.Body, Expression.Invoke(fn2, fn1.Parameters[0]));
var lambda = Expression.Lambda<Func<TFoo, string>>(body, fn1.Parameters[0]);
这是最简单的方法,但会为 Entity Framework 和不支持调用表达式的类似方法创建不受支持的表达式。
第二种方法使用简单的参数替换器帮助程序将第二个 lambda 表达式主体重新绑定到第一个 lambda 表达式参数:
public static class ExpressionUtils
{
public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
{
return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
}
class ParameterReplacer : ExpressionVisitor
{
public ParameterExpression Source;
public Expression Target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == Source ? Target : base.VisitParameter(node);
}
}
}
像这样
var body = Expression.Coalesce(fn1.Body,
fn2.Body.ReplaceParameter(fn2.Parameters[0], fn1.Parameters[0]));
var lambda = Expression.Lambda<Func<TFoo, string>>(body, fn1.Parameters[0]);