/// <summary> /// Visits the instance function. /// </summary> private static void VisitFunc(MethodCallExpression expression, CacheQueryExpressionVisitor visitor, string func, string suffix, params int[] adjust) { visitor.ResultBuilder.Append(func).Append("("); var isInstanceMethod = expression.Object != null; if (isInstanceMethod) { visitor.Visit(expression.Object); } for (int i = 0; i < expression.Arguments.Count; i++) { var arg = expression.Arguments[i]; if (isInstanceMethod || (i > 0)) { visitor.ResultBuilder.Append(", "); } visitor.Visit(arg); AppendAdjustment(visitor, adjust, i + 1); } visitor.ResultBuilder.Append(suffix).Append(")"); AppendAdjustment(visitor, adjust, 0); }
/// <summary> /// Visits the constant call expression. /// </summary> public static bool VisitConstantCall(ConstantExpression expression, CacheQueryExpressionVisitor visitor) { if (expression.Type != typeof(RegexOptions)) { return(false); } var regexOptions = expression.Value as RegexOptions? ?? RegexOptions.None; var result = string.Empty; foreach (var option in RegexOptionFlags) { if (regexOptions.HasFlag(option.Key)) { result += option.Value; regexOptions &= ~option.Key; } } if (regexOptions != RegexOptions.None) { throw new NotSupportedException(string.Format("RegexOptions.{0} is not supported", regexOptions)); } visitor.AppendParameter(result); return(true); }
/// <summary> /// Visits the SQL like expression. /// </summary> private static void VisitSqlLike(MethodCallExpression expression, CacheQueryExpressionVisitor visitor, string likeFormat) { visitor.ResultBuilder.Append("("); visitor.Visit(expression.Object); visitor.ResultBuilder.AppendFormat(" like {0}) ", likeFormat); var arg = expression.Arguments[0] as ConstantExpression; var paramValue = arg != null ? arg.Value : visitor.RegisterEvaluatedParameter(expression.Arguments[0]); visitor.Parameters.Add(paramValue); }
/// <summary> /// Visits the method call expression. /// </summary> public static void VisitMethodCall(MethodCallExpression expression, CacheQueryExpressionVisitor visitor) { var mtd = expression.Method; VisitMethodDelegate del; if (!Delegates.TryGetValue(mtd, out del)) { throw new NotSupportedException(string.Format("Method not supported: {0}.({1})", mtd.DeclaringType == null ? "static" : mtd.DeclaringType.FullName, mtd)); } del(expression, visitor); }
/// <summary> /// Visits the instance function for Trim specific handling. /// </summary> private static void VisitParameterizedTrimFunc(MethodCallExpression expression, CacheQueryExpressionVisitor visitor, string func) { visitor.ResultBuilder.Append(func).Append("("); visitor.Visit(expression.Object); var arg = expression.Arguments[0]; if (arg != null) { visitor.ResultBuilder.Append(", "); if (arg.NodeType == ExpressionType.Constant) { var constant = (ConstantExpression)arg; if (constant.Value is char) { visitor.AppendParameter((char)constant.Value); } else { var args = constant.Value as IEnumerable <char>; if (args == null) { throw new NotSupportedException("String.Trim function only supports IEnumerable<char>"); } var enumeratedArgs = args.ToArray(); if (enumeratedArgs.Length != 1) { throw new NotSupportedException("String.Trim function only supports a single argument: " + expression); } visitor.AppendParameter(enumeratedArgs[0]); } } else { visitor.Visit(arg); } } visitor.ResultBuilder.Append(")"); }
/// <summary> /// Visits member expression argument. /// </summary> private static void VisitArg(CacheQueryExpressionVisitor visitor, MethodCallExpression expression, int idx, bool lower) { if (lower) { visitor.ResultBuilder.Append("lower("); } visitor.Visit(expression.Arguments[idx]); if (lower) { visitor.ResultBuilder.Append(")"); } }
/// <summary> /// Visits string.Compare method /// </summary> private static void VisitStringCompare(MethodCallExpression expression, CacheQueryExpressionVisitor visitor, bool ignoreCase) { // Ex: nvl2(?, casewhen(_T0.NAME = ?, 0, casewhen(_T0.NAME >= ?, 1, -1)), 1) visitor.ResultBuilder.Append("nvl2("); visitor.Visit(expression.Arguments[1]); visitor.ResultBuilder.Append(", casewhen("); VisitArg(visitor, expression, 0, ignoreCase); visitor.ResultBuilder.Append(" = "); VisitArg(visitor, expression, 1, ignoreCase); visitor.ResultBuilder.Append(", 0, casewhen("); VisitArg(visitor, expression, 0, ignoreCase); visitor.ResultBuilder.Append(" >= "); VisitArg(visitor, expression, 1, ignoreCase); visitor.ResultBuilder.Append(", 1, -1)), 1)"); }
/// <summary> /// Appends the adjustment. /// </summary> private static void AppendAdjustment(CacheQueryExpressionVisitor visitor, int[] adjust, int idx) { if (idx < adjust.Length) { var delta = adjust[idx]; if (delta > 0) { visitor.ResultBuilder.AppendFormat(" + {0}", delta); } else if (delta < 0) { visitor.ResultBuilder.AppendFormat(" {0}", delta); } } }
/// <summary> /// Visits the property call expression. /// </summary> public static bool VisitPropertyCall(MemberExpression expression, CacheQueryExpressionVisitor visitor) { string funcName; if (!Properties.TryGetValue(expression.Member, out funcName)) { return(false); } visitor.ResultBuilder.Append(funcName).Append('('); visitor.Visit(expression.Expression); visitor.ResultBuilder.Append(')'); return(true); }
/// <summary> /// Visits the instance function. /// </summary> private static void VisitFunc(MethodCallExpression expression, CacheQueryExpressionVisitor visitor, string func, string suffix, params int[] adjust) { visitor.ResultBuilder.Append(func).Append("("); var isInstanceMethod = expression.Object != null; if (isInstanceMethod) { visitor.Visit(expression.Object); } for (int i = 0; i < expression.Arguments.Count; i++) { var arg = expression.Arguments[i]; if (isInstanceMethod || (i > 0)) { visitor.ResultBuilder.Append(", "); } if (arg.NodeType == ExpressionType.NewArrayInit) { // Only trim methods use params[], only one param is supported var args = ((NewArrayExpression)arg).Expressions; if (args.Count != 1) { throw new NotSupportedException("Method call only supports a single parameter: " + expression); } visitor.Visit(args[0]); } else { visitor.Visit(arg); } AppendAdjustment(visitor, adjust, i + 1); } visitor.ResultBuilder.Append(suffix).Append(")"); AppendAdjustment(visitor, adjust, 0); }