AssemblySorter.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace HybridCLR.Editor.Meta
  7. {
  8. public class AssemblySorter
  9. {
  10. class Node
  11. {
  12. public string Name;
  13. public List<Node> Dependencies = new List<Node>();
  14. public Node(string name)
  15. {
  16. Name = name;
  17. }
  18. }
  19. class TopologicalSorter
  20. {
  21. public static List<Node> Sort(List<Node> nodes)
  22. {
  23. List<Node> sorted = new List<Node>();
  24. HashSet<Node> visited = new HashSet<Node>();
  25. HashSet<Node> tempMarks = new HashSet<Node>();
  26. foreach (var node in nodes)
  27. {
  28. if (!visited.Contains(node))
  29. {
  30. Visit(node, visited, tempMarks, sorted);
  31. }
  32. }
  33. return sorted;
  34. }
  35. private static void Visit(Node node, HashSet<Node> visited, HashSet<Node> tempMarks, List<Node> sorted)
  36. {
  37. if (tempMarks.Contains(node))
  38. {
  39. throw new Exception("Detected cyclic dependency!");
  40. }
  41. if (!visited.Contains(node))
  42. {
  43. tempMarks.Add(node);
  44. foreach (var dependency in node.Dependencies)
  45. {
  46. Visit(dependency, visited, tempMarks, sorted);
  47. }
  48. tempMarks.Remove(node);
  49. visited.Add(node);
  50. sorted.Add(node);
  51. }
  52. }
  53. }
  54. private static List<string> SortAssemblyByReferenceOrder(IEnumerable<string> assemblies, Dictionary<string, HashSet<string>> refs)
  55. {
  56. var nodes = new List<Node>();
  57. var nodeMap = new Dictionary<string, Node>();
  58. foreach (var assembly in assemblies)
  59. {
  60. var node = new Node(assembly);
  61. nodes.Add(node);
  62. nodeMap.Add(assembly, node);
  63. }
  64. foreach (var assembly in assemblies)
  65. {
  66. var node = nodeMap[assembly];
  67. foreach (var refAssembly in refs[assembly])
  68. {
  69. node.Dependencies.Add(nodeMap[refAssembly]);
  70. }
  71. }
  72. var sortedNodes = TopologicalSorter.Sort(nodes);
  73. return sortedNodes.Select(node => node.Name).ToList();
  74. }
  75. public static List<string> SortAssemblyByReferenceOrder(IEnumerable<string> assemblies, IAssemblyResolver assemblyResolver)
  76. {
  77. var assCache = new AssemblyCache(assemblyResolver);
  78. var assRefAssemblies = new Dictionary<string, HashSet<string>>();
  79. foreach (var assName in assemblies)
  80. {
  81. var refAssemblies = new HashSet<string>();
  82. var mod = assCache.LoadModule(assName, false);
  83. foreach (var refAss in mod.GetAssemblyRefs())
  84. {
  85. if (assemblies.Contains(refAss.Name.ToString()))
  86. {
  87. refAssemblies.Add(refAss.Name.ToString());
  88. }
  89. }
  90. assRefAssemblies.Add(assName, refAssemblies);
  91. }
  92. return SortAssemblyByReferenceOrder(assemblies, assRefAssemblies);
  93. }
  94. }
  95. }