public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(EnumerableMethod.First, EnumerableMethod.FirstWithPredicate, EnumerableMethod.Last, EnumerableMethod.LastWithPredicate))
            {
                var sourceExpression  = arguments[0];
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);
                var array             = sourceTranslation.Ast;
                var itemSerializer    = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);

                if (method.IsOneOf(EnumerableMethod.FirstWithPredicate, EnumerableMethod.LastWithPredicate))
                {
                    var predicateLambda      = (LambdaExpression)arguments[1];
                    var predicateTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, predicateLambda, itemSerializer, asRoot: false);
                    var predicateParameter   = predicateLambda.Parameters[0];
                    array = AstExpression.Filter(
                        input: array,
                        cond: predicateTranslation.Ast,
                        @as: predicateParameter.Name);
                }

                var ast = method.Name == "First" ? AstExpression.First(array) : AstExpression.Last(array);
                return(new AggregationExpression(expression, ast, itemSerializer));
            }

            if (WindowMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(WindowMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

            throw new ExpressionNotSupportedException(expression);
        }
예제 #2
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            if (WindowMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(WindowMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

            throw new ExpressionNotSupportedException(expression);
        }
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__averageMethods))
            {
                var sourceExpression  = arguments[0];
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);

                AstExpression ast;
                if (method.IsOneOf(__averageWithSelectorMethods))
                {
                    var selectorLambda       = (LambdaExpression)arguments[1];
                    var selectorParameter    = selectorLambda.Parameters[0];
                    var sourceItemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                    var selectorSymbol       = context.CreateSymbol(selectorParameter, sourceItemSerializer);
                    var selectorContext      = context.WithSymbol(selectorSymbol);
                    var selectorTranslation  = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body);

                    ast = AstExpression.Avg(
                        AstExpression.Map(
                            input: sourceTranslation.Ast,
                            @as: selectorSymbol.Var,
                            @in: selectorTranslation.Ast));
                }
                else
                {
                    ast = AstExpression.Avg(sourceTranslation.Ast);
                }
                IBsonSerializer serializer = expression.Type switch
                {
                    Type t when t == typeof(int) => new Int32Serializer(),
                    Type t when t == typeof(long) => new Int64Serializer(),
                    Type t when t == typeof(float) => new SingleSerializer(),
                    Type t when t == typeof(double) => new DoubleSerializer(),
                    Type t when t == typeof(decimal) => new DecimalSerializer(),
                    Type {
                        IsConstructedGenericType : true
                    } t when t.GetGenericTypeDefinition() == typeof(Nullable <>) => (IBsonSerializer)Activator.CreateInstance(typeof(NullableSerializer <>).MakeGenericType(t.GenericTypeArguments[0])),
                    _ => throw new ExpressionNotSupportedException(expression)
                };

                return(new AggregationExpression(expression, ast, serializer));
            }

            if (WindowMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(WindowMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

            throw new ExpressionNotSupportedException(expression);
        }
    }
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__countMethods))
            {
                var sourceExpression  = arguments[0];
                var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);

                AstExpression ast;
                if (method.IsOneOf(__countWithPredicateMethods))
                {
                    if (sourceExpression.Type == typeof(string))
                    {
                        throw new ExpressionNotSupportedException(expression);
                    }

                    var predicateLambda      = (LambdaExpression)arguments[1];
                    var sourceItemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                    var predicateTranslation = ExpressionToAggregationExpressionTranslator.TranslateLambdaBody(context, predicateLambda, sourceItemSerializer, asRoot: false);
                    var filteredSourceAst    = AstExpression.Filter(
                        input: sourceTranslation.Ast,
                        cond: predicateTranslation.Ast,
                        @as: predicateLambda.Parameters[0].Name);
                    ast = AstExpression.Size(filteredSourceAst);
                }
                else
                {
                    if (sourceExpression.Type == typeof(string))
                    {
                        ast = AstExpression.StrLenCP(sourceTranslation.Ast);
                    }
                    else
                    {
                        ast = AstExpression.Size(sourceTranslation.Ast);
                    }
                }
                var serializer = GetSerializer(expression.Type);

                return(new AggregationExpression(expression, ast, serializer));
            }

            if (WindowMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(WindowMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

            throw new ExpressionNotSupportedException(expression);
        }
예제 #5
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.DeclaringType == typeof(Enumerable) && (method.Name == "Max" || method.Name == "Min"))
            {
                var             sourceExpression  = arguments[0];
                var             sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);
                AstExpression   ast;
                IBsonSerializer serializer;
                if (arguments.Count == 1)
                {
                    var array = sourceTranslation.Ast;
                    ast        = method.Name == "Max" ? AstExpression.Max(array) : AstExpression.Min(array);
                    serializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                }
                else
                {
                    var selectorLambda              = (LambdaExpression)arguments[1];
                    var selectorParameter           = selectorLambda.Parameters[0];
                    var selectorParameterSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                    var selectorParameterSymbol     = context.CreateSymbol(selectorParameter, selectorParameterSerializer);
                    var selectorContext             = context.WithSymbol(selectorParameterSymbol);
                    var selectorTranslation         = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body);
                    var mappedArray =
                        AstExpression.Map(
                            input: sourceTranslation.Ast,
                            @as: selectorParameterSymbol.Var,
                            @in: selectorTranslation.Ast);
                    ast        = method.Name == "Max" ? AstExpression.Max(mappedArray) : AstExpression.Min(mappedArray);
                    serializer = selectorTranslation.Serializer;
                }
                return(new AggregationExpression(expression, ast, serializer));
            }

            if (WindowMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(WindowMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

            throw new ExpressionNotSupportedException(expression);
        }
예제 #6
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (method.IsOneOf(__sumMethods))
            {
                var sourceExpression     = arguments[0];
                var sourceTranslation    = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);
                var sourceItemSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);

                AstExpression   ast;
                IBsonSerializer serializer;
                if (arguments.Count == 1)
                {
                    ast        = AstExpression.Sum(sourceTranslation.Ast);
                    serializer = sourceItemSerializer;
                }
                else
                {
                    var selectorLambda      = (LambdaExpression)arguments[1];
                    var selectorParameter   = selectorLambda.Parameters[0];
                    var selectorSymbol      = context.CreateSymbol(selectorParameter, sourceItemSerializer);
                    var selectorContext     = context.WithSymbol(selectorSymbol);
                    var selectorTranslation = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body);
                    ast = AstExpression.Sum(
                        AstExpression.Map(
                            input: sourceTranslation.Ast,
                            @as: selectorSymbol.Var,
                            @in: selectorTranslation.Ast));
                    serializer = selectorTranslation.Serializer;
                }

                return(new AggregationExpression(expression, ast, serializer));
            }

            if (WindowMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(WindowMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

            throw new ExpressionNotSupportedException(expression);
        }
예제 #7
0
        public static AggregationExpression Translate(TranslationContext context, MethodCallExpression expression)
        {
            var method    = expression.Method;
            var arguments = expression.Arguments;

            if (IsStandardDeviationMethod(method, out var stddevOperator))
            {
                if (arguments.Count == 1 || arguments.Count == 2)
                {
                    var sourceExpression  = arguments[0];
                    var sourceTranslation = ExpressionToAggregationExpressionTranslator.TranslateEnumerable(context, sourceExpression);

                    if (arguments.Count == 2)
                    {
                        var selectorLambda              = (LambdaExpression)arguments[1];
                        var selectorParameter           = selectorLambda.Parameters[0];
                        var selectorParameterSerializer = ArraySerializerHelper.GetItemSerializer(sourceTranslation.Serializer);
                        var selectorParameterSymbol     = context.CreateSymbol(selectorParameter, selectorParameterSerializer);
                        var selectorContext             = context.WithSymbol(selectorParameterSymbol);
                        var selectorTranslation         = ExpressionToAggregationExpressionTranslator.Translate(selectorContext, selectorLambda.Body);
                        var selectorAst = AstExpression.Map(
                            input: sourceTranslation.Ast,
                            @as: selectorParameterSymbol.Var,
                            @in: selectorTranslation.Ast);
                        var selectorResultSerializer = BsonSerializer.LookupSerializer(selectorLambda.ReturnType);
                        sourceTranslation = new AggregationExpression(selectorLambda, selectorAst, selectorResultSerializer);
                    }

                    var ast        = AstExpression.StdDev(stddevOperator, sourceTranslation.Ast);
                    var serializer = BsonSerializer.LookupSerializer(expression.Type);
                    return(new AggregationExpression(expression, ast, serializer));
                }
            }

            if (WindowMethodToAggregationExpressionTranslator.CanTranslate(expression))
            {
                return(WindowMethodToAggregationExpressionTranslator.Translate(context, expression));
            }

            throw new ExpressionNotSupportedException(expression);
        }