替换表达式正文中的参数名称
我正在尝试基于Specification对象动态构建表达式。
我创建了一个ExpressionHelper类,它有一个私有的表达式,如下所示:
private Expression<Func> expression; public ExpressionHelper() { expression = (Expression<Func>)(a => true); }
然后一些简单的方法如下:
public void And(Expression<Func> exp);
我正在和And方法的身体挣扎。 我基本上想要从exp
删除主体,将所有参数替换为expression
的参数,然后将其附加到expression
主体的末尾和AndAlso。
我做到了这个:
var newBody = Expression.And(expression.Body,exp.Body); expression = expression.Update(newBody, expression.Parameters);
但最终我的表达看起来像这样:
{ a => e.IsActive && e.IsManaged }
有更简单的方法吗? 或者我怎样才能撕掉那些e并用一个替换它们?
这里最简单的方法是Expression.Invoke
,例如:
public static Expression> AndAlso( Expression> x, Expression> y) { return Expression.Lambda>( Expression.AndAlso(x.Body, Expression.Invoke(y, x.Parameters)), x.Parameters); }
这适用于LINQ-to-Objects和LINQ-to-SQL,但EF不支持。 对于EF,你可能需要使用访问者重写树,遗憾的是。
使用以下代码: 在c#中组合两个lambda表达式
public static Expression> AndAlso( Expression> x, Expression> y) { var newY = new ExpressionRewriter().Subst(y.Parameters[0], x.Parameters[0]).Inline().Apply(y.Body); return Expression.Lambda>( Expression.AndAlso(x.Body, newY), x.Parameters); }
或者在.NET 4.0中,使用ExpressionVisitor
:
class ParameterVisitor : ExpressionVisitor { private readonly ReadOnlyCollection from, to; public ParameterVisitor( ReadOnlyCollection from, ReadOnlyCollection to) { if(from == null) throw new ArgumentNullException("from"); if(to == null) throw new ArgumentNullException("to"); if(from.Count != to.Count) throw new InvalidOperationException( "Parameter lengths must match"); this.from = from; this.to = to; } protected override Expression VisitParameter(ParameterExpression node) { for (int i = 0; i < from.Count; i++) { if (node == from[i]) return to[i]; } return node; } } public static Expression> AndAlso( Expression> x, Expression> y) { var newY = new ParameterVisitor(y.Parameters, x.Parameters) .VisitAndConvert(y.Body, "AndAlso"); return Expression.Lambda>( Expression.AndAlso(x.Body, newY), x.Parameters); }