【手撸一个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(); } } } }