• 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> ReBuildExpression(Expression<Func<string, bool>> lambd0, Expression<Func<string, bool>> lambd1)
            {
                parameter = Expression.Parameter(typeof(string), "name");
                Expression left = lambd0.Body;
                Expression right = lambd1.Body;
                BinaryExpression expression = Expression.AndAlso(left, 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 SetParamExpressionVisitor(ParameterExpression parameter) {
                this.Parameter = parameter;
            }
            public Expression Modify(Expression exp)
            {
                return this.Visit(exp);
            }
            protected override Expression VisitParameter(ParameterExpression parameter)
            {
                return this.Parameter;
            }
        }
    public static Func<string, bool> AndAlsoExpression(Expression<Func<string,bool>> exp1,Expression<Func<string, bool>> exp2)
            {
                var parameter = Expression.Parameter(typeof(string), "name");
                SetParamExpressionVisitor visitor = new SetParamExpressionVisitor(parameter);
                var newExp1 = visitor.Modify(exp1.Body);
                var newExp2 = visitor.Modify(exp2.Body);
                var newBodyExp = Expression.AndAlso(newExp1, 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 = AndAlsoExpression(exp1, 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.Compose(exp2, Expression.AndAlso);
            }
            public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> exp1, Expression<Func<T, bool>> exp2)
            {
                return exp1.Compose(exp2, 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.Parameter(typeof(string), "name");
                SetParamExpressionVisitor visitor = new SetParamExpressionVisitor(parameter);
                var newExp1 = visitor.Modify(exp1.Body);
                var newExp2 = visitor.Modify(exp2.Body);
                var newBodyExp = merge(newExp1, 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.Not(exp.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.Compose(exp2, Expression.AndAlso);
            }
            public static Expression<Predicate<T>> Or<T>(this Expression<Predicate<T>> exp1, Expression<Predicate<T>> exp2)
            {
                return exp1.Compose(exp2, 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.Parameter(typeof(T), "name");
                SetParamExpressionVisitor visitor = new SetParamExpressionVisitor(parameter);
                var newExp1 = visitor.Modify(exp1.Body);
                var newExp2 = visitor.Modify(exp2.Body);
                var newBodyExp = merge(newExp1, 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.Not(exp.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.And(exp2).Compile();
    Func<string, bool> func = exp1.Or(exp2).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)

    未完待续...

  • 相关阅读:
    GDAL指定自定义的金字塔目录
    同一个脚本在SQLPLUS和SQLDEV上的不同
    【LeetCode-面试算法经典-Java实现】【062-Unique Paths(唯一路径)】
    unity3d的playmaker插件使用教程,三、对象出入触发,声音播放
    MapReduce实现矩阵乘法
    Nginx+Tomcat搭建高性能负载均衡集群
    怎么去掉Xcodeproject中的某种类型的警告 Implicit conversion loses integer precision: &#39;NSInteger&#39; (aka &#39;long&#39;) to &#39;int32
    <html>
    实战c++中的vector系列--vector&lt;unique_ptr&lt;&gt;&gt;初始化(全部权转移)
    [Mac] mac linux 多线程下载利器 axel
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/12128845.html
Copyright © 2020-2023  润新知