【手撸一个ORM】第四步、Expression(表达式目录树)扩展

到这里,Orm的基架已经搭起来了,接下来就是激动人心的部分,表达式目录树转Sql语句,SqlDataReader转数据实体等等,但是在这之前,我们需要扩展下表达式目录树的方法,以方便后面的相关操作。

表达式目录树解析时需要的扩展方法

  • 表达式操作符转SQL操作符,这个没什么好说的,根据表达式类型获取相应的sql操作符,如 NodeType == ExpressionType.Equal,则返回 " = "。
  • 获取MemberExpression的根类型。在园子里表达式目录树相关文章中少有涉及,但这个很重要,在拼接sql语句时,很多时候我们需要根据该类型进行不同的操作,如 根类型为 Parameter,表达式将转换为 [表名].[列名] 字符串,若为其他,则会尝试对表达式进行求值。
  • 获取表达式目录路的值,如果是 常数类型,直接返回该节点的值,如果是其他类型,则尝试转为Lambda表达式,并对Lambda表达式进行求值返回。
using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace MyOrm.Expressions
{
    public static class ExpressionExtensions
    {
        public static string ToSqlOperator(this ExpressionType type)
        {
            switch (type)
            {
                case (ExpressionType.AndAlso):
                case (ExpressionType.And):
                    return " AND ";
                case (ExpressionType.OrElse):
                case (ExpressionType.Or):
                    return " OR ";
                case (ExpressionType.Not):
                    return " NOT ";
                case (ExpressionType.NotEqual):
                    return "<>";
                case ExpressionType.GreaterThan:
                    return ">";
                case ExpressionType.GreaterThanOrEqual:
                    return ">=";
                case ExpressionType.LessThan:
                    return "<";
                case ExpressionType.LessThanOrEqual:
                    return "<=";
                case (ExpressionType.Equal):
                    return "=";
                default:
                    throw new Exception("不支持该方法");
            }
        }

        public static ExpressionType GetRootType(this MemberExpression expression, out Stack<string> stack)
        {
            var memberExpr = expression;
            var parentExpr = expression.Expression;

            stack = new Stack<string>();
            stack.Push(expression.Member.Name);

            while (parentExpr != null && parentExpr.NodeType == ExpressionType.MemberAccess)
            {
                memberExpr = (MemberExpression)parentExpr;
                parentExpr = ((MemberExpression)parentExpr).Expression;
                stack.Push(memberExpr.Member.Name);
            }

            return parentExpr?.NodeType ?? memberExpr.NodeType;
        }

        public static object GetValue(this Expression expression)
        {
            if (expression.NodeType == ExpressionType.Constant)
            {
                return ((ConstantExpression)expression).Value;
            }
            else
            {
                var cast = Expression.Convert(expression, typeof(object));
                return Expression.Lambda<Func<object>>(cast).Compile().Invoke();
            }
        }
    }
}

 

posted @ 2019-04-06 23:14  没追求的码农  阅读(607)  评论(0编辑  收藏  举报