protected virtual void VisitConstant(ConstantExpression c, SqlVistorFlag flag) { var value = c.Value ?? "null"; if (flag.is_right) { var paraName = GetCustomParaName(flag.para_pretoken); // flag.GetCustomParaName(); flag.Append(paraName, true); if (c.Type.IsEnum) { AddParameter(paraName, (int)c.Value); } else if (c.Type == typeof(bool)) { AddParameter(paraName, (bool)value ? 1 : 0); } else { AddParameter(paraName, value); } } else { flag.Append(value.ToString()); } }
protected virtual void VisitUnary(UnaryExpression u, SqlVistorFlag flag) { var nodeType = flag.unary_type; flag.unary_type = u.NodeType; Visit(u.Operand, flag); flag.unary_type = nodeType; }
private void MethodCallLike(MethodCallExpression exp, SqlVistorFlag flag) { Visit(exp.Object, flag); flag.Append(GetUnaryOperater(flag.unary_type)); flag.Append(" LIKE CONCAT('%',"); VisitRight(exp.Arguments[0], flag); flag.Append(",'%')"); }
/// <summary> /// 递归解析时,保留上层的IsRight状态 /// </summary> /// <param name="exp"></param> /// <param name="flag"></param> protected virtual void VisitRight(Expression exp, SqlVistorFlag flag) { var isRight = flag.is_right; flag.is_right = true; Visit(exp, flag); flag.is_right = isRight; // 回归 }
protected virtual void VisitNew(NewExpression nex, SqlVistorFlag flag) { for (var i = 0; i < nex.Members.Count; i++) { var arg = nex.Arguments[i]; var member = nex.Members[i]; flag.Append(flag.GetColName(member.Name)).Append("="); VisitRight(arg, flag); } }
protected virtual void VisitMethodCall(MethodCallExpression exp, SqlVistorFlag flag) { var methodName = exp.Method.Name; switch (methodName) //这里其实还可以改成反射调用,不用写switch { case "Contains": MethodCallLike(exp, flag); break; // todo 补充其他方法 } }
protected virtual void VisitMember(MemberExpression exp, SqlVistorFlag flag) { if (exp.Expression != null && exp.Expression.NodeType == ExpressionType.Parameter) { if (flag.is_right && flag.vistor_type == SqlVistorType.Update) { var proParaName = flag.GetParaName(exp.Member.Name); flag.Append(proParaName, true); AddMemberProperty(proParaName, exp.Member.Name); } else { if (exp.Member.DeclaringType.GetTypeInfo().IsGenericType && exp.Member.DeclaringType?.GetGenericTypeDefinition() == typeof(Nullable <>)) { if (exp.Member.Name == "Value") { Visit(exp.Expression, flag); } if (exp.Member.Name != "HasValue") { return; } var doesNotEqualNull = Expression.MakeBinary(ExpressionType.NotEqual, exp.Expression, Expression.Constant(null)); Visit(doesNotEqualNull, flag); } else { flag.Append(flag.GetColName(exp.Member.Name), true); } } } else { var value = Expression.Lambda(exp).Compile().DynamicInvoke(); Visit(Expression.Constant(value), flag); } }
protected void VisitNewArray(NewArrayExpression na, SqlVistorFlag flag) { var original = na.Expressions; for (int i = 0, n = original.Count; i < n; i++) { var e = original[i]; if (e.NodeType == ExpressionType.NewArrayInit || e.NodeType == ExpressionType.NewArrayBounds) { if (e is NewArrayExpression newArrayExpression) { VisitNewArray(newArrayExpression, flag); } } else { Visit(e, flag); } } }
protected virtual void VisitBinary(BinaryExpression exp, SqlVistorFlag flag) { var operand = GetBinaryOperater(exp.NodeType); if (exp.NodeType == ExpressionType.AndAlso || exp.NodeType == ExpressionType.OrElse) { flag.Append("("); Visit(exp.Left, flag); flag.Append(") ").Append(operand).Append(" ("); Visit(exp.Right, flag); flag.Append(")"); } else { Visit(exp.Left, flag); flag.Append(operand); VisitRight(exp.Right, flag); } }
/// <summary> /// 处理where条件表达式,如果表达式为空,默认使用Id /// </summary> /// <param name="visitor"></param> /// <param name="exp"></param> /// <param name="visType"></param> private static string GetVisitExpressSql(SqlExpressionVisitor visitor, Expression exp, SqlVistorType visType) { if (visType == SqlVistorType.Update) { var updateFlag = new SqlVistorFlag(SqlVistorType.Update); visitor.Visit(exp, updateFlag); return(updateFlag.sql); } string sql; if (exp == null) { throw new ArgumentNullException("whereExp", "where表达式不能为空!"); } else { var whereFlag = new SqlVistorFlag(SqlVistorType.Where); visitor.Visit(exp, whereFlag); sql = string.Concat(" WHERE ", whereFlag.sql); } return(sql); }
/// <summary> /// 递归解析方法入口 /// </summary> /// <param name="exp"></param> /// <param name="flag"></param> public virtual void Visit(Expression exp, SqlVistorFlag flag) { switch (exp.NodeType) { case ExpressionType.Lambda: VisitLambda(exp as LambdaExpression, flag); break; case ExpressionType.MemberAccess: VisitMember(exp as MemberExpression, flag); break; case ExpressionType.Add: case ExpressionType.AddChecked: case ExpressionType.Subtract: case ExpressionType.SubtractChecked: case ExpressionType.Multiply: case ExpressionType.MultiplyChecked: case ExpressionType.Divide: case ExpressionType.Modulo: case ExpressionType.And: case ExpressionType.AndAlso: case ExpressionType.Or: case ExpressionType.OrElse: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: case ExpressionType.Equal: case ExpressionType.NotEqual: case ExpressionType.Coalesce: case ExpressionType.ArrayIndex: case ExpressionType.RightShift: case ExpressionType.LeftShift: case ExpressionType.ExclusiveOr: VisitBinary(exp as BinaryExpression, flag); break; case ExpressionType.Negate: case ExpressionType.NegateChecked: case ExpressionType.Not: case ExpressionType.Convert: case ExpressionType.ConvertChecked: case ExpressionType.ArrayLength: case ExpressionType.Quote: case ExpressionType.TypeAs: VisitUnary(exp as UnaryExpression, flag); break; case ExpressionType.Constant: VisitConstant(exp as ConstantExpression, flag); break; case ExpressionType.Parameter: VisitParameter(exp as ParameterExpression, flag); break; case ExpressionType.Call: VisitMethodCall(exp as MethodCallExpression, flag); break; case ExpressionType.New: VisitNew(exp as NewExpression, flag); break; case ExpressionType.NewArrayInit: case ExpressionType.NewArrayBounds: VisitNewArray(exp as NewArrayExpression, flag); break; case ExpressionType.MemberInit: VisitMemberInit(exp as MemberInitExpression, flag); break; case ExpressionType.Conditional: VisitConditional(exp as ConditionalExpression); break; } }
protected virtual void VisitParameter(ParameterExpression parameterExpression, SqlVistorFlag flag) { // todo }
protected virtual void VisitMemberInit(MemberInitExpression memberInitExpression, SqlVistorFlag flag) { // todo }
protected virtual void VisitLambda(LambdaExpression lambda, SqlVistorFlag flag) { Visit(lambda.Body, flag); }