// public methods
 /// <summary>
 /// Returns a string that represents the Expression.
 /// </summary>
 /// <param name="node">The Expression to format.</param>
 /// <returns>A string that represents the Expression.</returns>
 public static string ToString(Expression node)
 {
     var formatter = new ExpressionFormatter();
     formatter.Visit(node);
     return formatter.ToString();
 }
Example #2
0
        /// <summary>
        /// Translates a LINQ query expression tree.
        /// </summary>
        /// <param name="expression">The LINQ query expression tree.</param>
        public void Translate(Expression expression)
        {
            // when we reach the original MongoQueryable<TDocument> we're done
            var constantExpression = expression as ConstantExpression;

            if (constantExpression != null)
            {
                if (constantExpression.Type == typeof(SequoiaQueryable <>).MakeGenericType(DocumentType))
                {
                    return;
                }
            }

            var methodCallExpression = expression as MethodCallExpression;

            if (methodCallExpression != null)
            {
                TranslateMethodCall(methodCallExpression);
                return;
            }

            var message = string.Format("Don't know how to translate expression: {0}.", ExpressionFormatter.ToString(expression));

            throw new NotSupportedException(message);
        }
Example #3
0
        private void TranslateMethodCall(MethodCallExpression methodCallExpression)
        {
            if (methodCallExpression.Arguments.Count == 0)
            {
                var message = string.Format("Method call expression has no arguments: {0}.", ExpressionFormatter.ToString(methodCallExpression));
                throw new ArgumentOutOfRangeException("methodCallExpression", message);
            }

            var source = methodCallExpression.Arguments[0];

            Translate(source);
            _lastExpression = source;

            if (_distinct != null)
            {
                var message = "No further operators may follow Distinct in a LINQ query.";
                throw new NotSupportedException(message);
            }

            var methodName = methodCallExpression.Method.Name;

            switch (methodName)
            {
            case "Any":
                TranslateAny(methodCallExpression);
                break;

            case "Count":
            case "LongCount":
                TranslateCount(methodCallExpression);
                break;

            case "Distinct":
                TranslateDistinct(methodCallExpression);
                break;

            case "ElementAt":
            case "ElementAtOrDefault":
                TranslateElementAt(methodCallExpression);
                break;

            case "First":
            case "FirstOrDefault":
            case "Single":
            case "SingleOrDefault":
                TranslateFirstOrSingle(methodCallExpression);
                break;

            case "Last":
            case "LastOrDefault":
                TranslateLast(methodCallExpression);
                break;

            case "Max":
            case "Min":
                TranslateMaxMin(methodCallExpression);
                break;

            case "OfType":
                TranslateOfType(methodCallExpression);
                break;

            case "OrderBy":
            case "OrderByDescending":
                TranslateOrderBy(methodCallExpression);
                break;

            case "Select":
                TranslateSelect(methodCallExpression);
                break;

            case "Skip":
                TranslateSkip(methodCallExpression);
                break;

            case "Take":
                TranslateTake(methodCallExpression);
                break;

            case "ThenBy":
            case "ThenByDescending":
                TranslateThenBy(methodCallExpression);
                break;

            case "WithIndex":
                TranslateWithIndex(methodCallExpression);
                break;

            case "Where":
                TranslateWhere(methodCallExpression);
                break;

            default:
                var message = string.Format("The {0} query operator is not supported.", methodName);
                throw new NotSupportedException(message);
            }
        }
        // private static methods
        private static Type GetDocumentType(Expression expression)
        {
            // look for the innermost nested constant of type MongoQueryable<T> and return typeof(T)
            var constantExpression = expression as ConstantExpression;

            if (constantExpression != null)
            {
                var constantType = constantExpression.Type;
                if (constantType.IsGenericType)
                {
                    var genericTypeDefinition = constantType.GetGenericTypeDefinition();
                    if (genericTypeDefinition == typeof(SequoiaQueryable <>))
                    {
                        return(constantType.GetGenericArguments()[0]);
                    }
                }
            }

            var methodCallExpression = expression as MethodCallExpression;

            if (methodCallExpression != null && methodCallExpression.Arguments.Count != 0)
            {
                return(GetDocumentType(methodCallExpression.Arguments[0]));
            }

            var message = string.Format("Unable to find document type of expression: {0}.", ExpressionFormatter.ToString(expression));

            throw new ArgumentOutOfRangeException("expression", message);
        }