• C# 表达式树Expression


    表达式相加

    //常量表达式
    Expression firstArg = Expression.Constant(2);
    Expression secondArg = Expression.Constant(4);
    
    //相加
    Expression addExpression = Expression.Add(firstArg, secondArg);
    Console.WriteLine(addExpression.ToString());
    

    将表达式编译成委托

    Console.WriteLine("将表达式编译成委托");
    Expression<Func<int>> expression = Expression.Lambda<Func<int>>(addExpression);
    Console.WriteLine(expression);
    
    var func = expression.Compile();
    Console.WriteLine(func);
    Console.WriteLine("结果:" + func());
    

    将Lamda表达式转换成表达式

    Expression<Func<int>> expression = () => 5;
    
    Console.WriteLine(expression);
    Console.WriteLine(expression.Compile());
    Console.WriteLine(expression.Compile()());
    

    获得表达式信息

    Expression<Func<int, int, double, double>> expression = (num1, num2, num3) => (num1 + 5) * num2 / num3;
    Console.WriteLine(expression.ToString());
    Console.WriteLine(expression.Compile());
    Console.WriteLine(expression.Compile()(1, 2, 3));
    
    if (expression.NodeType == ExpressionType.Lambda)
    {
        //LambdaExpression继承于Expression
        var lambdaExpression = expression as LambdaExpression;
        Console.WriteLine(lambdaExpression.Body);
        Console.WriteLine("返回值类型:" + lambdaExpression.ReturnType.ToString());
    
        IReadOnlyList<ParameterExpression> parameters = lambdaExpression.Parameters;
    
        foreach (var parameter in parameters)
        {
            Console.WriteLine("形参名: " + parameter.Name);
            Console.WriteLine("形参类型: " + parameter.Type.Name);
        }
    }
    

    拆分左右节点

    Console.WriteLine("表达式详细信息");
    Console.WriteLine();
    
    //基本信息
    Expression<Func<int, int, int>> sumExpression = (num1, num2) => num1 + (5 + num2);
    Console.WriteLine($"根节点的节点类型:{sumExpression.NodeType}");
    Console.WriteLine($"根节点的类型:{sumExpression.Type.Name}");
    Console.WriteLine($"根节点的名字:{sumExpression.Name}");
    Console.WriteLine($"根节点的代码:{sumExpression.ToString()}");
    Console.WriteLine();
    
    //形参
    Console.WriteLine($@"表达式的形参:{sumExpression.Parameters.Count}个,");
    foreach (var item in sumExpression.Parameters)
    {
        Console.WriteLine($"节点的节点类型:{sumExpression.Parameters[0].NodeType},");
        Console.WriteLine($"类型:{sumExpression.Parameters[0].Type.Name},");
        Console.WriteLine($"参数的名字:{sumExpression.Parameters[0]}");
    }
    Console.WriteLine();
    
    //Body
    var sumBody = sumExpression.Body as BinaryExpression;
    
    Console.WriteLine($"主体节点的节点类型:{sumBody.NodeType}");
    Console.WriteLine($"主体节点代码:{sumBody.ToString()}");
    Console.WriteLine();
    
    //左节点
    var leftNode = sumBody.Left as ParameterExpression;
    Console.WriteLine($"主体左节点:{leftNode.ToString()}");
    Console.WriteLine($"主体左节点的节点类型:{leftNode.NodeType}");
    Console.WriteLine($"主体左节点的类型:{leftNode.Type.Name}");
    Console.WriteLine($"主体左节点的名字:{leftNode.Name}");
    Console.WriteLine();
    
    //右节点
    var rightNode = sumBody.Right as BinaryExpression;
    Console.WriteLine($"主体右节点:{rightNode.ToString()}");
    Console.WriteLine($"主体右节点的节点类型:{rightNode.NodeType}");
    Console.WriteLine($"主体右节点的类型:{rightNode.Type.Name}");
    Console.WriteLine();
    
    //继续拆分右节点
    //(5 + num2)
    //右节点的左节点
    var rightLeftNode = rightNode.Left as ConstantExpression;
    Console.WriteLine($"右节点的左节点:{rightLeftNode.ToString()}");
    Console.WriteLine($"右节点的左节点的节点类型:{rightLeftNode.NodeType}");
    Console.WriteLine($"右节点的左节点的类型:{rightLeftNode.Type.Name}");
    Console.WriteLine();
    
    //右节点的右节点
    var rightRightNode = rightNode.Right as ParameterExpression;
    Console.WriteLine($"右节点的右节点:{rightRightNode.ToString()}");
    Console.WriteLine($"右节点的右节点的节点类型:{rightRightNode.NodeType}");
    Console.WriteLine($"右节点的右节点的类型:{rightRightNode.Type.Name}");
    Console.WriteLine($"右节点的右节点的名字:{rightRightNode.Name}");
    

    示例代码

    ExpressionTestDemo

    参考资料

    表达式树 (C#)
    Expression.NodeType 属性

  • 相关阅读:
    基金相关知识整理
    Apache Shiro反序列化漏洞复现
    payload分离免杀
    Red Team 工具集之网络钓鱼和水坑攻击
    GPP(Group Policy Preference)组策略偏好漏洞利用
    AdFind
    python爬虫之beautifulsoup的使用
    xargs命令_Linux xargs命令:一个给其他命令传递参数的过滤器
    mutillidae之注册页面的Insert型报错注入
    mutillidae之Insert型注入
  • 原文地址:https://www.cnblogs.com/Lulus/p/15990390.html
Copyright © 2020-2023  润新知