组合两个表达式(表达式<Func<T,bool>)我有两个类型的表达式Expression<Func<T, bool>>我想要得到或,或者不是这些,得到一个相同类型的新表达式。Expression<Func<T, bool>> expr1;Expression<Func<T, bool>> expr2;...//how to do this (the code below will obviously not work)
Expression<Func<T, bool>> andExpression = expr AND expr2
3 回答
墨色风雨
TA贡献1853条经验 获得超6个赞
Expression.AndAlso
/ OrElse
ParameterExpression
var body = Expression.AndAlso(expr1.Body, expr2.Body);var lambda = Expression.Lambda<Func<T,bool>>(body, expr1.Parameters[0]);
static Expression<Func<T, bool>> Not<T>( this Expression<Func<T, bool>> expr){ return Expression.Lambda<Func<T, bool>>( Expression.Not(expr.Body), expr.Parameters[0]);}
Invoke
:
// OrElse is very similar...static Expression<Func<T, bool>> AndAlso<T>( this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right){ var param = Expression.Parameter(typeof(T), "x"); var body = Expression.AndAlso( Expression.Invoke(left, param), Expression.Invoke(right, param) ); var lambda = Expression.Lambda<Func<T, bool>>(body, param); return lambda;}
Invoke
static Expression<Func<T, bool>> AndAlso<T>( this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2){ // need to detect whether they use the same // parameter instance; if not, they need fixing ParameterExpression param = expr1.Parameters[0]; if (ReferenceEquals(param, expr2.Parameters[0])) { // simple version return Expression.Lambda<Func<T, bool>>( Expression.AndAlso(expr1.Body, expr2.Body), param); } // otherwise, keep expr1 "as is" and invoke expr2 return Expression.Lambda<Func<T, bool>>( Expression.AndAlso( expr1.Body, Expression.Invoke(expr2, param)), param);}
public static Expression<Func<T, bool>> AndAlso<T>( this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) { var parameter = Expression.Parameter(typeof (T)); var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter); var left = leftVisitor.Visit(expr1.Body); var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter); var right = rightVisitor.Visit(expr2.Body); return Expression.Lambda<Func<T, bool>>( Expression.AndAlso(left, right), parameter); } private class ReplaceExpressionVisitor : ExpressionVisitor { private readonly Expression _oldValue; private readonly Expression _newValue; public ReplaceExpressionVisitor(Expression oldValue, Expression newValue) { _oldValue = oldValue; _newValue = newValue; } public override Expression Visit(Expression node) { if (node == _oldValue) return _newValue; return base.Visit(node); } }
Qyouu
TA贡献1786条经验 获得超11个赞
var filterC = filterA.And(filterb);
public static class PredicateBuilder { public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> a, Expression<Func<T, bool>> b) { ParameterExpression p = a.Parameters[0]; SubstExpressionVisitor visitor = new SubstExpressionVisitor(); visitor.subst[b.Parameters[0]] = p; Expression body = Expression.AndAlso(a.Body, visitor.Visit(b.Body)); return Expression.Lambda<Func<T, bool>>(body, p); } public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> a, Expression<Func<T, bool>> b) { ParameterExpression p = a.Parameters[0]; SubstExpressionVisitor visitor = new SubstExpressionVisitor(); visitor.subst[b.Parameters[0]] = p; Expression body = Expression.OrElse(a.Body, visitor.Visit(b.Body)); return Expression.Lambda<Func<T, bool>>(body, p); } }
internal class SubstExpressionVisitor : System.Linq.Expressions.ExpressionVisitor { public Dictionary<Expression, Expression> subst = new Dictionary<Expression, Expression>(); protected override Expression VisitParameter(ParameterExpression node) { Expression newValue; if (subst.TryGetValue(node, out newValue)) { return newValue; } return node; } }
- 3 回答
- 0 关注
- 1685 浏览
添加回答
举报
0/150
提交
取消