Expression笔记-ExpressionVisitor介绍及案例

介绍:

案例1:使用已有表达式树构建新的表达式树

Expression<Func<string, bool>> lambda0 = item => item.Length > 2;
Expression<Func<string, bool>> lambda1 = item => item.Length < 4;

将上面两个表达式合并成一个 item=>item.Length>&& 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)

未完待续…

Published by

风君子

独自遨游何稽首 揭天掀地慰生平