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.

143 lines
5.2 KiB

  1. using IPA.Config.Data;
  2. using IPA.Config.Stores.Attributes;
  3. using IPA.Logging;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Reflection;
  8. using System.Reflection.Emit;
  9. using System.Text;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using System.Linq.Expressions;
  13. using System.Runtime.CompilerServices;
  14. using System.IO;
  15. using Boolean = IPA.Config.Data.Boolean;
  16. using System.Collections;
  17. using IPA.Utilities;
  18. using System.ComponentModel;
  19. #if NET3
  20. using Net3_Proxy;
  21. using Array = Net3_Proxy.Array;
  22. #endif
  23. [assembly: InternalsVisibleTo(IPA.Config.Stores.GeneratedStore.AssemblyVisibilityTarget)]
  24. namespace IPA.Config.Stores
  25. {
  26. internal static partial class GeneratedStoreImpl
  27. {
  28. private static readonly Dictionary<Type, (GeneratedStoreCreator ctor, Type type)> generatedCreators = new Dictionary<Type, (GeneratedStoreCreator ctor, Type type)>();
  29. public static T Create<T>() where T : class => (T)Create(typeof(T));
  30. public static IConfigStore Create(Type type) => Create(type, null);
  31. private static readonly MethodInfo CreateGParent =
  32. typeof(GeneratedStoreImpl).GetMethod(nameof(Create), BindingFlags.NonPublic | BindingFlags.Static, null,
  33. CallingConventions.Any, new[] { typeof(IGeneratedStore) }, Array.Empty<ParameterModifier>());
  34. internal static T Create<T>(IGeneratedStore parent) where T : class => (T)Create(typeof(T), parent);
  35. private static IConfigStore Create(Type type, IGeneratedStore parent)
  36. => GetCreator(type)(parent);
  37. internal static GeneratedStoreCreator GetCreator(Type t)
  38. {
  39. if (generatedCreators.TryGetValue(t, out var gen))
  40. return gen.ctor;
  41. else
  42. {
  43. gen = MakeCreator(t);
  44. generatedCreators.Add(t, gen);
  45. return gen.ctor;
  46. }
  47. }
  48. internal static Type GetGeneratedType(Type t)
  49. {
  50. if (generatedCreators.TryGetValue(t, out var gen))
  51. return gen.type;
  52. else
  53. {
  54. gen = MakeCreator(t);
  55. generatedCreators.Add(t, gen);
  56. return gen.type;
  57. }
  58. }
  59. internal const string GeneratedAssemblyName = "IPA.Config.Generated";
  60. private static AssemblyBuilder assembly = null;
  61. private static AssemblyBuilder Assembly
  62. {
  63. get
  64. {
  65. if (assembly == null)
  66. {
  67. var name = new AssemblyName(GeneratedAssemblyName);
  68. assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
  69. }
  70. return assembly;
  71. }
  72. }
  73. internal static void DebugSaveAssembly(string file)
  74. {
  75. Assembly.Save(file);
  76. }
  77. private static ModuleBuilder module = null;
  78. private static ModuleBuilder Module
  79. {
  80. get
  81. {
  82. if (module == null)
  83. module = Assembly.DefineDynamicModule(Assembly.GetName().Name, Assembly.GetName().Name + ".dll");
  84. return module;
  85. }
  86. }
  87. private static readonly Dictionary<Type, Dictionary<Type, FieldInfo>> TypeRequiredConverters = new Dictionary<Type, Dictionary<Type, FieldInfo>>();
  88. private static void CreateAndInitializeConvertersFor(Type type, IEnumerable<SerializedMemberInfo> structure)
  89. {
  90. if (!TypeRequiredConverters.TryGetValue(type, out var converters))
  91. {
  92. var converterFieldType = Module.DefineType($"{type.FullName}<Converters>",
  93. TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Abstract | TypeAttributes.AnsiClass); // a static class
  94. var uniqueConverterTypes = structure.Where(m => m.HasConverter).Select(m => m.Converter).Distinct().ToArray();
  95. converters = new Dictionary<Type, FieldInfo>(uniqueConverterTypes.Length);
  96. foreach (var convType in uniqueConverterTypes)
  97. {
  98. var field = converterFieldType.DefineField($"<converter>_{convType}", convType,
  99. FieldAttributes.FamORAssem | FieldAttributes.InitOnly | FieldAttributes.Static);
  100. converters.Add(convType, field);
  101. }
  102. var cctor = converterFieldType.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes);
  103. {
  104. var il = cctor.GetILGenerator();
  105. foreach (var kvp in converters)
  106. {
  107. var typeCtor = kvp.Key.GetConstructor(Type.EmptyTypes);
  108. il.Emit(OpCodes.Newobj, typeCtor);
  109. il.Emit(OpCodes.Stsfld, kvp.Value);
  110. }
  111. il.Emit(OpCodes.Ret);
  112. }
  113. TypeRequiredConverters.Add(type, converters);
  114. converterFieldType.CreateType();
  115. }
  116. foreach (var member in structure.Where(m => m.HasConverter))
  117. member.ConverterField = converters[member.Converter];
  118. }
  119. }
  120. }