using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace HybridCLR.Editor.Meta { public class AssemblySorter { class Node { public string Name; public List Dependencies = new List(); public Node(string name) { Name = name; } } class TopologicalSorter { public static List Sort(List nodes) { List sorted = new List(); HashSet visited = new HashSet(); HashSet tempMarks = new HashSet(); foreach (var node in nodes) { if (!visited.Contains(node)) { Visit(node, visited, tempMarks, sorted); } } return sorted; } private static void Visit(Node node, HashSet visited, HashSet tempMarks, List sorted) { if (tempMarks.Contains(node)) { throw new Exception("Detected cyclic dependency!"); } if (!visited.Contains(node)) { tempMarks.Add(node); foreach (var dependency in node.Dependencies) { Visit(dependency, visited, tempMarks, sorted); } tempMarks.Remove(node); visited.Add(node); sorted.Add(node); } } } private static List SortAssemblyByReferenceOrder(IEnumerable assemblies, Dictionary> refs) { var nodes = new List(); var nodeMap = new Dictionary(); foreach (var assembly in assemblies) { var node = new Node(assembly); nodes.Add(node); nodeMap.Add(assembly, node); } foreach (var assembly in assemblies) { var node = nodeMap[assembly]; foreach (var refAssembly in refs[assembly]) { node.Dependencies.Add(nodeMap[refAssembly]); } } var sortedNodes = TopologicalSorter.Sort(nodes); return sortedNodes.Select(node => node.Name).ToList(); } public static List SortAssemblyByReferenceOrder(IEnumerable assemblies, IAssemblyResolver assemblyResolver) { var assCache = new AssemblyCache(assemblyResolver); var assRefAssemblies = new Dictionary>(); foreach (var assName in assemblies) { var refAssemblies = new HashSet(); var mod = assCache.LoadModule(assName, false); foreach (var refAss in mod.GetAssemblyRefs()) { if (assemblies.Contains(refAss.Name.ToString())) { refAssemblies.Add(refAss.Name.ToString()); } } assRefAssemblies.Add(assName, refAssemblies); } return SortAssemblyByReferenceOrder(assemblies, assRefAssemblies); } } }