/// <summary>
        /// Resolves types for the specified expression.
        /// </summary>
        /// <param name="expression">The expression to resolve types for.</param>
        /// <returns>Expression with resolved types.</returns>
        public QueryExpression Visit(LinqGroupByExpression expression)
        {
            var source          = this.ResolveTypes(expression.Source);
            var sourceType      = ValidateSourceIsACollection(source);
            var keySelector     = this.ResolveLambdaTypes(expression.KeySelector, sourceType);
            var elementSelector = expression.ElementSelector != null?this.ResolveLambdaTypes(expression.ElementSelector, sourceType) : null;

            var keyCollectionType     = keySelector.Body.ExpressionType.CreateCollectionType();
            var elementCollectionType = expression.ElementSelector != null?elementSelector.Body.ExpressionType.CreateCollectionType() : sourceType;

            if (expression.ResultSelector != null)
            {
                // resolve lambda strips the collection out of parameters, but the second parameter to the result is a collection
                // so we pass collection of collections
                var resultSelector = this.ResolveLambdaTypes(expression.ResultSelector, keyCollectionType, elementCollectionType.CreateCollectionType());
                var resultType     = resultSelector.Body.ExpressionType;

                return(new LinqGroupByExpression(source, keySelector, elementSelector, resultSelector, resultType.CreateCollectionType()));
            }
            else
            {
                var groupingType = new QueryGroupingType(keySelector.Body.ExpressionType, elementCollectionType.ElementType, this.EvaluationStrategy);

                return(new LinqGroupByExpression(source, keySelector, elementSelector, null, groupingType.CreateCollectionType()));
            }
        }
        /// <summary>
        /// Creates a QueryValue of a given type.
        /// </summary>
        /// <param name="type">Type of the QueryValue that will be generated.</param>
        /// <returns>QueryValue representing the provided object.</returns>
        public QueryValue Visit(QueryGroupingType type)
        {
            var resultFragment    = this.ResultFragmentStack.Pop();
            var groupingInterface = resultFragment.GetType().GetInterfaces().Where(i => i.IsGenericType() && i.GetGenericTypeDefinition() == typeof(IGrouping <,>)).SingleOrDefault();

            ExceptionUtilities.CheckObjectNotNull(groupingInterface, "Expecting result fragment to be a grouping.");

            Type keyType                = groupingInterface.GetGenericArguments()[0];
            Type elementType            = groupingInterface.GetGenericArguments()[1];
            var  generateGroupingMethod = typeof(ObjectToQueryValueConverter).GetMethods(false, false).Where(m => m.Name == "GenerateGroupingItem" && m.IsGenericMethod).Single();

            generateGroupingMethod = generateGroupingMethod.MakeGenericMethod(keyType, elementType);

            var resultGrouping = (QueryStructuralValue)generateGroupingMethod.Invoke(this, new[] { resultFragment, type });

            return(resultGrouping);
        }
        private QueryCollectionValue RewriteGroupingElements(QueryCollectionValue groupings, LinqLambdaExpression elementSelectorLambda)
        {
            var groupingElementType   = (QueryGroupingType)groupings.Type.ElementType;
            var rewrittenGroupingType = new QueryGroupingType(groupingElementType.Key.PropertyType, elementSelectorLambda.Body.ExpressionType, groupingElementType.EvaluationStrategy);

            var rewrittenGroupings = new List <QueryValue>();

            foreach (var grouping in groupings.Elements.Cast <QueryStructuralValue>())
            {
                QueryCollectionValue elements = grouping.GetCollectionValue("Elements");
                var rewrittenElements         = elements.Select(e => this.EvaluateLambda <QueryValue>(elementSelectorLambda, e));
                var rewrittenGrouping         = rewrittenGroupingType.CreateNewInstance();
                rewrittenGrouping.SetValue("Key", grouping.GetValue("Key"));
                rewrittenGrouping.SetValue("Elements", rewrittenElements);
                rewrittenGroupings.Add(rewrittenGrouping);
            }

            var result = rewrittenGroupingType.CreateCollectionType().CreateCollectionWithValues(rewrittenGroupings);

            return(result);
        }
 /// <summary>
 /// Visits a <see cref="QueryGroupingType"/>.
 /// </summary>
 /// <param name="type">Query type being visited.</param>
 /// <returns>The result of visiting this query type.</returns>
 public ComparisonResult Visit(QueryGroupingType type)
 {
     throw new TaupoNotSupportedException("Comparison of grouping value is not supported.");
 }
Example #5
0
 /// <summary>
 /// Visits a <see cref="QueryGroupingType"/>.
 /// </summary>
 /// <param name="type">Query type being visited.</param>
 /// <returns>The result of visiting this query type.</returns>
 public ComparisonResult Visit(QueryGroupingType type)
 {
     return(this.parent.CompareGrouping((QueryStructuralValue)this.expectedValue, this.actualValue, this.path, this.shouldThrow));
 }
        private QueryValue GenerateGroupingItem <TKey, TElement>(IGrouping <TKey, TElement> grouping, QueryGroupingType queryGroupingType)
        {
            var result        = queryGroupingType.CreateNewInstance();
            var keyValue      = this.Convert(grouping.Key, queryGroupingType.Key.PropertyType);
            var elementsValue = this.Convert(grouping.Select(g => g), queryGroupingType.Elements.PropertyType);

            result.SetValue("Key", keyValue);
            result.SetValue("Elements", elementsValue);

            return(result);
        }