public RemoteGroupExpressionCompiler(GroupingInfo[] grouping, SummaryInfo[] totalSummary, SummaryInfo[] groupSummary)
            : base(false)
        {
            _groupByParam = CreateItemParam(typeof(T));

            if (grouping != null)
            {
                foreach (var i in grouping)
                {
                    var selectorExpr = CompileAccessorExpression(_groupByParam, i.Selector);
                    if (!String.IsNullOrEmpty(i.GroupInterval))
                    {
                        var groupIntervalExpr = CompileGroupInterval(selectorExpr, i.GroupInterval);

                        if (Utils.CanAssignNull(selectorExpr.Type))
                        {
                            var nullableType = typeof(Nullable <>).MakeGenericType(groupIntervalExpr.Type);
                            var nullConst    = Expression.Constant(null, nullableType);
                            var test         = Expression.Equal(selectorExpr, nullConst);

                            groupIntervalExpr = Expression.Convert(groupIntervalExpr, nullableType);
                            selectorExpr      = Expression.Condition(test, nullConst, groupIntervalExpr);
                        }
                        else
                        {
                            selectorExpr = groupIntervalExpr;
                        }
                    }

                    _groupKeyExprList.Add(selectorExpr);
                    _descendingList.Add(i.Desc);
                }
            }

            if (totalSummary != null)
            {
                InitSummary(totalSummary, _totalSummaryExprList, _totalSummaryTypes, _totalSummaryParams);
            }

            if (_groupKeyExprList.Any() && groupSummary != null)
            {
                InitSummary(groupSummary, _groupSummaryExprList, _groupSummaryTypes, _groupSummaryParams);
            }

            var typeArguments = new[] { typeof(int) }
            .Concat(_groupKeyExprList.Concat(_totalSummaryExprList).Concat(_groupSummaryExprList).Select(i => i.Type))
            .ToArray();

            _remoteGroupType       = AnonType.Get(typeArguments);
            _remoteGroupTypeMarkup = new RemoteGroupTypeMarkup(_groupKeyExprList.Count, _totalSummaryExprList.Count, _groupSummaryExprList.Count);
        }
        public static RemoteGroupingResult Run(IEnumerable <AnonType> flatGroups, int groupCount, SummaryInfo[] totalSummary, SummaryInfo[] groupSummary)
        {
            var accessor = new AnonTypeAccessor();

            var markup = new RemoteGroupTypeMarkup(
                groupCount,
                totalSummary != null ? totalSummary.Length : 0,
                groupSummary != null ? groupSummary.Length : 0
                );

            List <Group> hierGroups = null;

            if (groupCount > 0)
            {
                hierGroups = new GroupHelper <AnonType>(accessor).Group(
                    flatGroups,
                    Enumerable.Range(0, groupCount).Select(i => new GroupingInfo {
                    Selector = AnonType.ITEM_PREFIX + (RemoteGroupTypeMarkup.KeysStartIndex + i)
                }).ToArray()
                    );
            }

            IEnumerable dataToAggregate = hierGroups;

            if (dataToAggregate == null)
            {
                dataToAggregate = flatGroups;
            }

            var transformedTotalSummary = TransformSummary(totalSummary, markup.TotalSummaryStartIndex);
            var transformedGroupSummary = TransformSummary(groupSummary, markup.GroupSummaryStartIndex);

            transformedTotalSummary.Add(new SummaryInfo {
                SummaryType = "remoteCount"
            });

            var totals     = new AggregateCalculator <AnonType>(dataToAggregate, accessor, transformedTotalSummary, transformedGroupSummary).Run();
            var totalCount = (int)totals.Last();

            totals = totals.Take(totals.Length - 1).ToArray();
            if (totals.Length < 1)
            {
                totals = null;
            }

            return(new RemoteGroupingResult {
                Groups = hierGroups,
                Totals = totals,
                TotalCount = totalCount
            });
        }