介绍:
案例1:使用已有表达式树构建新的表达式树
Expression<Func<string, bool>> lambda0 = item => item.Length > 2; Expression<Func<string, bool>> lambda1 = item => item.Length < 4;
将上面两个表达式合并成一个 item=>item.Length>2 && item.Length<4
不能直接使用下面这种方法构建新的表达式树,因为Body中带着之前的Parameter信息
public Func<string, bool> ReBuildExpressionExpression<Func<string, bool>> lambd0, Expression<Func<string, bool>> lambd1) { parameter = Expression.Parametertypeofstring), "name"); Expression left = lambd0.Body; Expression right = lambd1.Body; BinaryExpression expression = Expression.AndAlsoleft, right); Expression<Func<string, bool>> lambda = Expression.Lambda<Func<string, bool>>expression, parameter); return lambda.Compile); }
只能使用ExpressionVisitor修改表达式,将之前的Parameter替换成新的
public class SetParamExpressionVisitor : ExpressionVisitor { public ParameterExpression Parameter { get; set; } public SetParamExpressionVisitor) { } public SetParamExpressionVisitorParameterExpression parameter) { this.Parameter = parameter; } public Expression ModifyExpression exp) { return this.Visitexp); } protected override Expression VisitParameterParameterExpression parameter) { return this.Parameter; } }
public static Func<string, bool> AndAlsoExpressionExpression<Func<string,bool>> exp1,Expression<Func<string, bool>> exp2) { var parameter = Expression.Parametertypeofstring), "name"); SetParamExpressionVisitor visitor = new SetParamExpressionVisitorparameter); var newExp1 = visitor.Modifyexp1.Body); var newExp2 = visitor.Modifyexp2.Body); var newBodyExp = Expression.AndAlsonewExp1, newExp2); return Expression.Lambda<Func<string, bool>>newBodyExp, parameter).Compile); }
调用:
Expression<Func<string, bool>> exp1 = item => item.Length > 2; Expression<Func<string, bool>> exp2 = item => item.Length < 4; Func<string,bool> func = AndAlsoExpressionexp1, exp2); bool b = func"aaaa");//false
有了上面的基础,可以写几个扩展方法 And)、Or)、Not)
public static class ExpressionExtension { #region Expression<Func<T>>扩展 public static Expression<Func<T, bool>> And<T>this Expression<Func<T, bool>> exp1, Expression<Func<T, bool>> exp2) { return exp1.Composeexp2, Expression.AndAlso); } public static Expression<Func<T, bool>> Or<T>this Expression<Func<T, bool>> exp1, Expression<Func<T, bool>> exp2) { return exp1.Composeexp2, Expression.OrElse); } public static Expression<Func<T, bool>> Compose<T>this Expression<Func<T, bool>> exp1, Expression<Func<T, bool>> exp2, Func<Expression, Expression, Expression> merge) { var parameter = Expression.Parametertypeofstring), "name"); SetParamExpressionVisitor visitor = new SetParamExpressionVisitorparameter); var newExp1 = visitor.Modifyexp1.Body); var newExp2 = visitor.Modifyexp2.Body); var newBodyExp = mergenewExp1, newExp2); return Expression.Lambda<Func<T, bool>>newBodyExp, parameter); } public static Expression<Func<T, bool>> Not<T>this Expression<Func<T, bool>> exp) { return Expression.Lambda<Func<T, bool>>Expression.Notexp.Body), exp.Parameters[0]); } #endregion #region Expression<Predicate<T>>扩展 public static Expression<Predicate<T>> And<T>this Expression<Predicate<T>> exp1, Expression<Predicate<T>> exp2) { return exp1.Composeexp2, Expression.AndAlso); } public static Expression<Predicate<T>> Or<T>this Expression<Predicate<T>> exp1, Expression<Predicate<T>> exp2) { return exp1.Composeexp2, Expression.OrElse); } public static Expression<Predicate<T>> Compose<T>this Expression<Predicate<T>> exp1, Expression<Predicate<T>> exp2, Func<Expression, Expression, Expression> merge) { var parameter = Expression.ParametertypeofT), "name"); SetParamExpressionVisitor visitor = new SetParamExpressionVisitorparameter); var newExp1 = visitor.Modifyexp1.Body); var newExp2 = visitor.Modifyexp2.Body); var newBodyExp = mergenewExp1, newExp2); return Expression.Lambda<Predicate<T>>newBodyExp, parameter); } public static Expression<Predicate<T>> Not<T>this Expression<Predicate<T>> exp) { return Expression.Lambda<Predicate<T>>Expression.Notexp.Body), exp.Parameters[0]); } #endregion }
View Code
调用:
Expression<Func<string, bool>> exp1 = item => item.Length < 2; Expression<Func<string, bool>> exp2 = item => item.Length > 4; //Func<string, bool> func = exp1.Andexp2).Compile); Func<string, bool> func = exp1.Orexp2).Not).Compile); bool b = func"aaa");
参考:
https://www.cnblogs.com/FlyEdward/archive/2010/12/06/Linq_ExpressionTree7.html
https://www.cnblogs.com/snailblog/p/11525118.html(多个Parameter)
未完待续…