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.

115 lines
3.1 KiB

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