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> /// 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())); } }