You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
3.1 KiB

  1. using Mono.Cecil;
  2. using System.IO;
  3. using System.Linq;
  4. namespace CollectDependencies
  5. {
  6. class VirtualizedModule
  7. {
  8. private readonly FileInfo _file;
  9. private ModuleDefinition _module;
  10. public static VirtualizedModule Load(string engineFile)
  11. {
  12. return new VirtualizedModule(engineFile);
  13. }
  14. private VirtualizedModule(string assemblyFile)
  15. {
  16. _file = new FileInfo(assemblyFile);
  17. LoadModules();
  18. }
  19. private void LoadModules()
  20. {
  21. var resolver = new DefaultAssemblyResolver();
  22. resolver.AddSearchDirectory(_file.DirectoryName);
  23. var parameters = new ReaderParameters
  24. {
  25. AssemblyResolver = resolver,
  26. };
  27. _module = ModuleDefinition.ReadModule(_file.FullName, parameters);
  28. }
  29. /// <summary>
  30. ///
  31. /// </summary>
  32. /// <param name="targetFile"></param>
  33. public void Virtualize(string targetFile)
  34. {
  35. foreach (var type in _module.Types)
  36. {
  37. VirtualizeType(type);
  38. }
  39. _module.Write(targetFile);
  40. }
  41. private void VirtualizeType(TypeDefinition type)
  42. {
  43. if(type.IsSealed)
  44. {
  45. // Unseal
  46. type.IsSealed = false;
  47. }
  48. if (type.IsInterface) return;
  49. if (type.IsAbstract) return;
  50. // These two don't seem to work.
  51. if (type.Name == "SceneControl" || type.Name == "ConfigUI") return;
  52. // Take care of sub types
  53. foreach (var subType in type.NestedTypes)
  54. {
  55. VirtualizeType(subType);
  56. }
  57. foreach (var method in type.Methods)
  58. {
  59. if (method.IsManaged
  60. && method.IsIL
  61. && !method.IsStatic
  62. && !method.IsVirtual
  63. && !method.IsAbstract
  64. && !method.IsAddOn
  65. && !method.IsConstructor
  66. && !method.IsSpecialName
  67. && !method.IsGenericInstance
  68. && !method.HasOverrides)
  69. {
  70. method.IsVirtual = true;
  71. method.IsPublic = true;
  72. method.IsPrivate = false;
  73. method.IsNewSlot = true;
  74. method.IsHideBySig = true;
  75. }
  76. }
  77. foreach (var field in type.Fields)
  78. {
  79. if (field.IsPrivate) field.IsFamily = true;
  80. }
  81. }
  82. public bool IsVirtualized
  83. {
  84. get
  85. {
  86. var awakeMethods = _module.GetTypes().SelectMany(t => t.Methods.Where(m => m.Name == "Awake"));
  87. var methodDefinitions = awakeMethods as MethodDefinition[] ?? awakeMethods.ToArray();
  88. if (!methodDefinitions.Any()) return false;
  89. return ((float)methodDefinitions.Count(m => m.IsVirtual) / methodDefinitions.Count()) > 0.5f;
  90. }
  91. }
  92. }
  93. }