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