表达式树的解析(二)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 表达式树的解析(二)

升级


然而,实践工作中,大家都会写相对复杂或者说多个条件的表达式。那么再采用上面的方式是无法确认表达式节点的类型进行转换的。我们可以添加一个Visit方法,根据 NodeType 转换成对应的Expression的类型,从而方法访问对应的属性进行表达式解析。


但是,重写之前,我们得了解一件事,既然叫表达式树,意味着在子节点里,还会有多个节点,如下图:


image.png


那么,我们假设,只要是 BinaryExpression(二元运算表达式)就会有多个子节,去访问子节点就是一个递归的过程,而终点就是 MemberExpression  和 ConstantExpression,对应字段名称和常量值的拼接。


下面是代码实现:


public class ExpressionTypeHelper
    {
        public StringBuilder GeWhere = new StringBuilder(100);
        public string Where
        {
            get { return GeWhere.ToString(); }
        }
        public void ResolveExpression(Expression<Func<Users, bool>> expression)
        {
            Visit(expression.Body);
        }
        public void Visit(Expression expression)
        {
            switch (expression.NodeType)
            {
                case ExpressionType.Constant:
                    VisitConstantExpression(expression);
                    break;
                case ExpressionType.MemberAccess:
                    VisitMemberExpression(expression);
                    break;
                case ExpressionType.Convert:
                    VisitUnaryExpression(expression);
                    break;
                default:
                    VisitBinaryExpression(expression);
                    break;
            }
        }
        public void VisitUnaryExpression(Expression expression)
        {
            var e = (UnaryExpression)expression;
            Visit(e.Operand);
        }
        public void VisitBinaryExpression(Expression expression)
        {
            var e = (BinaryExpression)expression;
            GeWhere.Append("(");
            Visit(e.Left);
            GeWhere.Append(e.NodeType.TransferExpressionType());
            Visit(e.Right);
            GeWhere.Append(")");
        }
        public void VisitConstantExpression(Expression expression)
        {
            var e = (ConstantExpression)expression;
            if (e.Type == typeof(string))
            {
                GeWhere.Append("'" + e.Value + "'");
            }
            else
            {
                GeWhere.Append(e.Value);
            }
        }
        public void VisitMemberExpression(Expression expression)
        {
            var e = (MemberExpression)expression;
            GeWhere.Append(e.Member.Name);
        }
    }


结果如下:


image.png


ExpressionVisitor的使用


一个基本的表达式解析思路基本实现了,但是!随着自己的orm的完善是不是这么多种的Expression类型都得在Visit方法添一遍,不是的。


ExpressionVisitor类是提供给我们的表达式树解析的帮助类,我们只要定义一个类继承ExpressionVisitor,实现一个 ResolveExpression 入口方法,重写


VisitBinary、VisitConstant、VisitMember方法,代码如下:


public class ExpressionTrasfer : ExpressionVisitor
    {
        public StringBuilder GeWhere = new StringBuilder(100);
        public string Where
        {
            get { return GeWhere.ToString(); }
        }
        public void ResolveExpression(Expression<Func<Users, bool>> expression)
        {
            Visit(expression.Body);
        }
        protected override Expression VisitBinary(BinaryExpression node)
        {
            GeWhere.Append("(");
            Visit(node.Left);
            GeWhere.Append(node.NodeType.TransferExpressionType());
            Visit(node.Right);
            GeWhere.Append(")");
            return node;
        }
        protected override Expression VisitConstant(ConstantExpression node)
        {
            if (node.Type == typeof(string))
            {
                GeWhere.Append("'" + node.Value + "'");
            }
            else if (node.Type == typeof(int))
            {
                GeWhere.Append(node.Value);
            }
            return node;
        }
        protected override Expression VisitMember(MemberExpression node)
        {
            GeWhere.Append(node.Member.Name);
            return node;
        }
    }


结束


一个简单的表达式解析大致完成了,当然里面还有很多可以完善,例如值类型的判断,is 还是 = ,VisitMethodCall重写等等。原理就这样,实现我这里就不一一列举。


如对大家有帮助,麻烦请推荐,有不足请在下面评论提出,我会一一更改。

目录
相关文章
|
27天前
|
数据格式
常用的Lambda表达式案例解析,工作中都会用到!
常用的Lambda表达式案例解析,工作中都会用到!
|
3月前
|
Java API
Java 8新特性:Lambda表达式与Stream API的深度解析
【7月更文挑战第61天】本文将深入探讨Java 8中的两个重要特性:Lambda表达式和Stream API。我们将首先介绍Lambda表达式的基本概念和语法,然后详细解析Stream API的使用和优势。最后,我们将通过实例代码演示如何结合使用Lambda表达式和Stream API,以提高Java编程的效率和可读性。
|
4月前
|
SQL 开发框架 前端开发
在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
|
3月前
|
JSON 数据格式 索引
【Azure Developer】Azure Logic App 示例: 解析 Request Body 的 JSON 的表达式? triggerBody()?
【Azure Developer】Azure Logic App 示例: 解析 Request Body 的 JSON 的表达式? triggerBody()?
|
5月前
|
前端开发 安全 Java
Spring EL表达式:概念、特性与应用深入解析
Spring EL表达式:概念、特性与应用深入解析
|
5月前
深入解析AVL树:高效实现二叉平衡搜索树(2)
深入解析AVL树:高效实现二叉平衡搜索树
24 1
|
5月前
|
存储
深入解析AVL树:高效实现二叉平衡搜索树
深入解析AVL树:高效实现二叉平衡搜索树
21 1
|
5月前
|
存储 安全 Java
深入解析Java HashMap的高性能扩容机制与树化优化
深入解析Java HashMap的高性能扩容机制与树化优化
145 1
|
4月前
|
并行计算 Java 开发者
解析Java中的Lambda表达式用法
解析Java中的Lambda表达式用法
|
4月前
|
JavaScript
js 解析和操作树 —— 获取树的深度、提取并统计树的所有的节点和叶子节点、添加节点、修改节点、删除节点
js 解析和操作树 —— 获取树的深度、提取并统计树的所有的节点和叶子节点、添加节点、修改节点、删除节点
117 0

推荐镜像

更多