SqlSugar/SqlSugar/Abstract/LambdaExpressionsProvider/ResolveExpress/Main.cs
sunkaixuan 48630e4b6e -
2017-01-08 22:50:42 +08:00

361 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Reflection;
using System.Text.RegularExpressions;
namespace SqlSugar
{
/// <summary>
/// ** 描述:拉姆达解析类
/// ** 创始时间2015-7-20
/// ** 修改时间2016-9-26
/// ** 作者sunkaixuan
/// ** qq610262374
/// ** 使用说明:使用请注名作者
/// </summary>
internal partial class ResolveExpress
{
public SqlSugarClient Context { get; set; }
private ISqlBuilder SqlBuilder { get; set; }
private ResolveExpress() { }
private string ParSymbol { get; set; }
public ResolveExpress(SqlSugarClient context)
{
this.Context = context;
this.SqlBuilder = context.SqlBuilder;
this.ParSymbol = context.SqlBuilder.SqlParameterKeyWord;
}
/// <summary>
/// 解析拉姆达
/// </summary>
/// <param name="sameIndex">区分相同参数名的索引号</param>
public ResolveExpress(int sameIndex = 1)
{
this.SameIndex = sameIndex;
}
public string SqlWhere = null;
public ResolveExpressType Type = ResolveExpressType.WhereSingle;
public List<SqlParameter> Paras = new List<SqlParameter>();
private int SameIndex = 1;
private SqlSugarClient DB;
/// <summary>
/// 解析表达式
/// </summary>
/// <param name="re">当前解析对象</param>
/// <param name="exp">要解析的表达式</param>
/// <param name="db">数据库访问对象</param>
public void ResolveExpression(Expression exp)
{
DB = this.Context;
//初始化表达式
Init(this, exp);
}
public string GetLeftString(Expression exp)
{
var reval = Regex.Match(exp.ToString(), @"\((.+?)\).+").Groups[1].Value;
return reval;
}
public string[] GetLeftArray(Expression exp)
{
var reval = GetLeftString(exp).Split(',');
return reval;
}
/// <summary>
/// 初始化表达式
/// </summary>
/// <param name="re"></param>
/// <param name="exp"></param>
private void Init(ResolveExpress re, Expression exp)
{
ResolveExpress.MemberType type = ResolveExpress.MemberType.None;
this.SqlWhere = string.Format(" {1} {0} ", re.CreateSqlElements(exp, ref type, true), Context.SqlBuilder.LambadaQueryBuilder.WhereInfos.Count == 0 ? "WHERE" : "AND");
//还原bool值
foreach (var item in ConstantBoolDictionary)
{
if (this.SqlWhere.IsValuable())
{
this.SqlWhere = this.SqlWhere.Replace(item.Key.ToString(), item.ConditionalValue);
}
}
}
/// <summary>
/// 递归解析表达式路由计算
/// </summary>
/// <returns></returns>
private string CreateSqlElements(Expression exp, ref MemberType type, bool isTure, bool? isComparisonOperator = null)
{
//主入口
if (exp is LambdaExpression)
{
return LambdaExpression(exp);
}
else if (exp is BinaryExpression)
{
return BinaryExpression(exp);
}
else if (exp is BlockExpression)
{
throw new SqlSugarException(ExpBlockExpression + exp.ToString());
}
else if (exp is ConditionalExpression)
{
throw new SqlSugarException(ExpConditionalExpression + exp.ToString());
}
else if (exp is MethodCallExpression)
{
return MethodCallExpression(exp, ref type, isTure);
}
else if (exp is ConstantExpression)
{
return ConstantExpression(exp, ref type, isComparisonOperator);
}
else if (exp is MemberExpression)
{
return MemberExpression(ref exp, ref type, isComparisonOperator);
}
else if (exp is UnaryExpression)
{
return UnaryExpression(exp, ref type);
}
else if (exp != null && exp.NodeType.IsIn(ExpressionType.New, ExpressionType.NewArrayBounds, ExpressionType.NewArrayInit))
{
throw new SqlSugarException(ExpNew + exp.ToString());
}
return null;
}
/// <summary>
/// 将解析值赋给dynInv
/// </summary>
/// <param name="exp"></param>
/// <param name="me"></param>
/// <param name="dynInv"></param>
private static void SetMemberValueToDynInv(ref Expression exp, MemberExpression me, ref object dynInv)
{
var conExp = me.Expression as ConstantExpression;
var fieldInfo = me.Member as System.Reflection.FieldInfo;
if (conExp != null && fieldInfo != null)
{
dynInv = (fieldInfo).GetValue((me.Expression as ConstantExpression).Value);
if (fieldInfo.FieldType.IsEnum)
{
dynInv = Convert.ToInt64(Enum.ToObject(fieldInfo.FieldType, dynInv));
}
}
else
{
var memberInfos = new Stack<MemberInfo>();
// "descend" toward's the root object reference:
while (exp is MemberExpression)
{
var memberExpr = exp as MemberExpression;
memberInfos.Push(memberExpr.Member);
if (memberExpr.Expression == null)
{
if (memberExpr.Member.MemberType == MemberTypes.Property)
{
PropertyInfo pro = (PropertyInfo)memberExpr.Member;
dynInv = pro.GetValue(memberExpr.Member, null);
if (dynInv != null && dynInv.GetType().IsClass)
{
var fieldName = me.Member.Name;
var proInfo = dynInv.GetType().GetProperty(fieldName);
if (proInfo != null)
{
dynInv = proInfo.GetValue(dynInv, null);
}
var fieInfo = dynInv.GetType().GetField(fieldName);
if (fieInfo != null)
{
dynInv = fieInfo.GetValue(dynInv);
}
if (fieInfo == null && proInfo == null)
{
throw new SqlSugarException(string.Format(ExpNoSupportObjectOrAttr, dynInv.GetType().FullName, dynInv.GetType().FullName));
}
}
return;
}
else if (memberExpr.Member.MemberType == MemberTypes.Field)
{
FieldInfo field = (FieldInfo)memberExpr.Member;
dynInv = field.GetValue(memberExpr.Member);
if (dynInv != null && dynInv.GetType().IsClass)
{
var fieldName = me.Member.Name;
var proInfo = dynInv.GetType().GetProperty(fieldName);
if (proInfo != null)
{
dynInv = proInfo.GetValue(dynInv, null);
}
var fieInfo = dynInv.GetType().GetField(fieldName);
if (fieInfo != null)
{
dynInv = fieInfo.GetValue(dynInv);
}
if (fieInfo == null && proInfo == null)
{
throw new SqlSugarException(string.Format(ExpNoSupportObjectOrAttr, dynInv.GetType().FullName, dynInv.GetType().FullName));
}
}
return;
}
}
if (memberExpr.Expression == null)
{
dynInv = ExpErrorUniqueKey;
return;
}
exp = memberExpr.Expression;
}
// fetch the root object reference:
var constExpr = exp as ConstantExpression;
if (constExpr == null)
{
dynInv = ExpErrorUniqueKey;
return;
}
var objReference = constExpr.Value;
// "ascend" back whence we came from and resolve object references along the way:
while (memberInfos.Count > 0) // or some other break condition
{
var mi = memberInfos.Pop();
if (mi.MemberType == MemberTypes.Property)
{
var objProp = objReference.GetType().GetProperty(mi.Name);
if (objProp == null)
{
dynInv = ExpErrorUniqueKey;
return;
}
objReference = objProp.GetValue(objReference, null);
}
else if (mi.MemberType == MemberTypes.Field)
{
var objField = objReference.GetType().GetField(mi.Name);
if (objField == null)
{
dynInv = ExpErrorUniqueKey;
return;
}
objReference = objField.GetValue(objReference);
}
}
dynInv = objReference;
}
}
/// <summary>
/// 添加参数
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
private string AddParas(ref string left, object right)
{
string oldLeft = left;
left = left + SameIndex;
SameIndex++;
if (Type != ResolveExpressType.WhereSingle)
{
left = left.Replace(".", "_");
}
if (right == null)
{
this.Paras.Add(new SqlParameter(this.ParSymbol + left, DBNull.Value));
}
else
{
this.Paras.Add(new SqlParameter(this.ParSymbol + left, right));
}
return oldLeft;
}
/// <summary>
/// 添加参数并返回右边值
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
private string AddParasReturnRight(object left, ref string right)
{
string oldRight = right;
right = right + SameIndex;
SameIndex++;
if (Type != ResolveExpressType.WhereSingle)
{
right = right.Replace(".", "_");
}
if (left == null)
{
this.Paras.Add(new SqlParameter(this.ParSymbol + right, DBNull.Value));
}
else
{
this.Paras.Add(new SqlParameter(this.ParSymbol + right, left));
}
return oldRight;
}
/// <summary>
/// 根据条件生成对应的sql查询操作符
/// </summary>
/// <param name="expressiontype"></param>
/// <returns></returns>
private string GetOperator(ExpressionType expressiontype)
{
switch (expressiontype)
{
case ExpressionType.And:
case ExpressionType.AndAlso:
return " AND ";
case ExpressionType.Equal:
return " =";
case ExpressionType.GreaterThan:
return " >";
case ExpressionType.GreaterThanOrEqual:
return ">=";
case ExpressionType.LessThan:
return "<";
case ExpressionType.LessThanOrEqual:
return "<=";
case ExpressionType.NotEqual:
return "<>";
case ExpressionType.Or:
case ExpressionType.OrElse:
return " OR ";
case ExpressionType.Add:
case ExpressionType.AddChecked:
return "+";
case ExpressionType.Subtract:
case ExpressionType.SubtractChecked:
return "-";
case ExpressionType.Divide:
return "/";
case ExpressionType.Multiply:
case ExpressionType.MultiplyChecked:
return "*";
default:
throw new SqlSugarException(string.Format(OperatorError + expressiontype));
}
}
}
}