private List<string> VisitModule(GraphModule module, List<string> chains)
        {
            module.Visited = true;
            module.Returns = AllChildrenReturned(module) && AllChildrenVisited(module);

            if (IsIsolated(module)) {
                chains.Add(module.Name); //single module chain
            }
            else if (RequiresNone(module) && !AllChildrenReturned(module))
            {
                chains.Add(module.Name); //start of a new chain
            }
            else
            {
                chains[chains.Count-1] += module.Name; //append to current chain
            }
            if(module.RequiredBy.Any(child => child.Visited))
                throw new CircularDependencyException($"Module '{module}' has children already visited in chain '{chains.Last()}'");
            if (!module.Returns)
                chains = VisitModule(module.RequiredBy.First(child => child.Visited == false), chains);

            return chains;
        }
 private bool IsIsolated(GraphModule module)
 {
     return module.RequiredByNone && RequiresNone(module);
 }
 private bool RequiresNone(GraphModule module)
 {
     return _modules.Any(m => m.IsRequiredBy(module)) == false;
 }
 private bool AllParentsVisited(GraphModule module)
 {
     return _modules.All(m => m.RequiredBy.Contains(module) == false || m.Visited);
 }
 private static bool AllChildrenReturned(GraphModule module)
 {
     return module.RequiredByNone || module.RequiredBy.All(m => m.Returns);
 }
 private bool AllChildrenVisited(GraphModule module)
 {
     return module.RequiredByNone || module.RequiredBy.All(m => m.Visited);
 }
 public bool IsRequiredBy(GraphModule module)
 {
     return IsRequiredBy(module.Name);
 }