zoukankan      html  css  js  c++  java
  • 表达式树ExpressionTrees

    简介

    表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如方法调用和 x < y 这样的二元运算等。
    你可以对表达式树中的代码进行编辑和运算。这样能够动态修改可执行代码、在不同数据库中执行 LINQ 查询以及创建动态查询。
    表达式树还能用于动态语言运行时 (DLR) 以提供动态语言和 .NET Framework 之间的互操作性。

    一、Lambda 表达式创建表达式树

                Expression<Action<int>> actionExpression = n => Console.WriteLine(n);
                Expression<Func<int, bool>> funcExpression1 = (n) => n < 0;
                Expression<Func<int, int, bool>> funcExpression2 = (n, m) => n - m == 0;
                var lambda = actionExpression.Compile();
                lambda(11);//输出11
                Console.ReadLine();

    二、API 创建表达式树

                //通过 Expression 类创建表达式树
                //  lambda:num => num == 0
                ParameterExpression pExpression = Expression.Parameter(typeof(int));    //参数:num
                ConstantExpression cExpression = Expression.Constant(0);    //常量:0
                BinaryExpression bExpression = Expression.MakeBinary(ExpressionType.Equal, pExpression, cExpression);   //表达式:num == 0
                Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(bExpression, pExpression);  //lambda 表达式:num => num == 0
                var aa = lambda.Compile();
                Console.WriteLine("{0}", aa(11));   //false
                Console.WriteLine("{0}", aa(0));    //true
                Console.ReadLine();

    三、解析表达式树 

                Expression<Func<int, bool>> funcExpression = num => num == 0;
    
                //开始解析
                ParameterExpression pExpression = funcExpression.Parameters[0]; //lambda 表达式参数
                BinaryExpression body = (BinaryExpression)funcExpression.Body;  //lambda 表达式主体:num == 0
    
                Console.WriteLine($"解析:{pExpression.Name} => {body.Left} {body.NodeType} {body.Right}");
                Console.ReadLine();

    四、表达式树永久性

    表达式树应具有永久性(类似字符串)。这意味着如果你想修改某个表达式树,则必须复制该表达式树然后替换其中的节点来创建一个新的表达式树。  你可以使用表达式树访问者遍历现有表达式树。

    五、编译表达式树

                //Expression<TDelegate> 类型提供了 Compile 方法以将表达式树表示的代码编译成可执行委托。
                Expression<Func<string, int>> funcExpression = msg => msg.Length;
                //表达式树编译成委托
                var lambda = funcExpression.Compile();
                //调用委托
                Console.WriteLine(lambda("Hello, World!")); //13
    
                //语法简化
                Console.WriteLine(funcExpression.Compile()("Hello, World!")); //13
                Console.ReadLine();

    六、执行表达式树

                int n = 1;
                int m = 2;
                var p1 = Expression.Parameter(typeof(int), "num1");
                var p2 = Expression.Parameter(typeof(int), "num2");
                //待执行的表达式树
                BinaryExpression bExpression = Expression.Add(p1, p2);
                //创建 lambda 表达式
                Expression<Func<int,int,int>> funcExpression = Expression.Lambda<Func<int, int, int>>(bExpression, p1, p2);
                //编译 lambda 表达式
                Func<int, int, int> func = funcExpression.Compile();
    
                //执行 lambda 表达式
                Console.WriteLine($"{n} + {m} = {func(n,m)}");
                Console.ReadLine();

    七、修改表达式树

            static void Main(string[] args)
            {
                Expression<Func<int, bool>> funcExpression = num => num == 0;
                Console.WriteLine($"Source: {funcExpression}");//Source: num => (num == 0)
    
                var visitor = new NotEqualExpressionVisitor();
                var expression = visitor.Visit(funcExpression);
    
                Console.WriteLine($"Modify: {expression}");//Source: num => (num != 0)
    
                Console.Read();
            }
    
            /// <summary>
            /// 不等表达式树访问器
            /// </summary>
            public class NotEqualExpressionVisitor : ExpressionVisitor
            {
                public Expression Visit(BinaryExpression node)
                {
                    return VisitBinary(node);
                }
    
                protected override Expression VisitBinary(BinaryExpression node)
                {
                    //该类继承 ExpressionVisitor 类,通过 Visit 方法间接调用 VisitBinary 方法将 != 替换成 ==。基类方法构造类似于传入的表达式树的节点,但这些节点将其子目录树替换为访问器递归生成的表达式树。  
                    return node.NodeType == ExpressionType.Equal
                        ? Expression.MakeBinary(ExpressionType.NotEqual, node.Left, node.Right) //重新弄个表达式:用 != 代替 ==
                        : base.VisitBinary(node);
                }
            }
  • 相关阅读:
    c++中的stack实现
    非虚函数是静态绑定
    函数返回const,以便控制访问
    析构函数为虚函数
    c++中初始化列表顺序和声明顺序一致
    define的误用
    模板就是让编译器帮你写代码
    mysql代码中设置变量
    拼接index
    python import vs from import
  • 原文地址:https://www.cnblogs.com/lgxlsm/p/6756174.html
Copyright © 2011-2022 走看看