private void AddProjectToAggregationInfo(AggregationInfo aggregationInfo, Project project)
        {
            if (!aggregationInfo.BuildSet.Add(project))
            {
                return;
            }

            _logger.Debug("Add to aggregate root {name} @{path}"
                          , project.ProjectName
                          , project.Directory);

            var references = project
                             .GetPackageReferences()
                             .Select(reference => reference.Include)
                             .Distinct();

            foreach (var reference in references)
            {
                if (!aggregationInfo.ProjectDictionary.TryGetValue(reference, out var dependentProject))
                {
                    continue;
                }
                if (aggregationInfo.BuildSet.Contains(dependentProject))
                {
                    continue;
                }
                AddProjectToAggregationInfo(aggregationInfo, dependentProject);
            }

            aggregationInfo.OrderedList.AddLast(project);
        }
        public static LambdaExpression GetSimpleAggregate(AggregationInfo x, ParameterExpression grouppedParam)
        {
            LambdaExpression selectExpression;
            string           methodName = x.Aggregate.ToString();
            MethodInfo       method;
            var elementType = grouppedParam.Type.GetTypeInfo().GetInterface("IEnumerable`1").GetTypeInfo().GetGenericArguments().Single();

            if (string.IsNullOrWhiteSpace(x.SourcePropertyName))
            {
                selectExpression = null;
                method           = typeof(Enumerable).GetTypeInfo().GetMethods().Single(m => m.Name == methodName && m.GetParameters().Length == 1);
                method           = method.MakeGenericMethod(elementType);
            }
            else
            {
                var itemParam = Expression.Parameter(elementType, "item");
                selectExpression = ExpressionBuilder.Path(x.SourcePropertyName, itemParam);
                var returnType = selectExpression.ReturnType;
                if (returnType == typeof(Int16) || returnType == typeof(byte) || returnType == typeof(SByte) || returnType == typeof(UInt16))
                {
                    returnType       = typeof(int);
                    selectExpression = Expression.Lambda(Expression.Convert(selectExpression.Body, returnType), selectExpression.Parameters);
                }
                method = typeof(Enumerable).GetTypeInfo().GetMethods().Single(m => m.Name == methodName && m.GetParameters().Length == 2 &&
                                                                              m.GetParameters()[1].ParameterType.GetTypeInfo().GetGenericArguments().Last() == returnType);
                method = method.MakeGenericMethod(elementType);
            }
            var parameters = selectExpression == null ? new Expression[] { grouppedParam } : new Expression[] { grouppedParam, selectExpression };
            var invoke     = Expression.Call(method, parameters);

            return(Expression.Lambda(invoke, grouppedParam));
        }
        /// <summary>
        /// Aggregates the projects.
        /// </summary>
        public async Task AggregateProjectsAsync()
        {
            var projectPaths         = _projectSearchProvider.GetProjectPaths();
            var deserializationTasks = projectPaths
                                       .AsParallel()
                                       .Select(path => _projectBuilder.DeserializeFromXmlAsync(path));
            var projects = await Task.WhenAll(deserializationTasks);

            var aggregationInfo = new AggregationInfo
            {
                ProjectDictionary = projects.ToDictionary(project => project.ProjectName, StringComparer.OrdinalIgnoreCase),
                BuildSet          = new HashSet <Project>(projects.Length),
                OrderedList       = new LinkedList <Project>()
            };

            foreach (var project in projects.OrderBy(p => p.ProjectName))
            {
                AddProjectToAggregationInfo(aggregationInfo, project);
            }

            _outputChannel.DisplayOutput(aggregationInfo.OrderedList
                                         , (IReadOnlyDictionary <string, Project>)aggregationInfo.ProjectDictionary);
        }