private MethodDefinition CreateRegisterMethod() { MethodDefinition method = new MethodDefinition("Generated__RegisterExposedTypes", MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static, module.ImportReference(typeof(void))); CustomAttribute a; if (isBuildingPlayer) { a = new CustomAttribute(module.GetConstructor <RuntimeInitializeOnLoadMethodAttribute>(typeof(RuntimeInitializeLoadType))); a.ConstructorArguments.Add(new CustomAttributeArgument(module.GetTypeReference <RuntimeInitializeLoadType>(), RuntimeInitializeLoadType.BeforeSceneLoad)); } else { a = new CustomAttribute(module.GetConstructor <InitializeOnLoadMethodAttribute>()); } method.CustomAttributes.Add(a); MethodReference registerType = module.GetMethod(typeof(LevelEditorSerializer), "RegisterType", typeof(int)); ILProcessor il = method.Body.GetILProcessor(); for (int i = 0; i < types.Count; i++) { GenericInstanceMethod m = new GenericInstanceMethod(registerType); m.GenericArguments.Add(module.ImportReference(types[i])); il.EmitInt(types[i].FullName.GetStableHashCode()); il.Emit(OpCodes.Call, m); if (types[i].TryResolve(out TypeDefinition type) && type.TryGetAttributes <FormerlyHashedAsAttribute>(out CustomAttribute[] formerHashedAttributes)) { for (int j = 0; j < formerHashedAttributes.Length; j++) { il.EmitInt(formerHashedAttributes[j].GetConstructorArgument(0, string.Empty).GetStableHashCode()); il.Emit(OpCodes.Call, module.GetMethod(typeof(LevelEditorSerializer), "RegisterType", typeof(int)).MakeGenericMethod(module.ImportReference(type))); } } } il.Emit(OpCodes.Ret); return(method); }
public static MethodDefinition CreateSpanMethod(ModuleDefinition module, string name, TypeDefinition type) { TypeReference span = module.ImportReference(typeof(ReadOnlySpan <byte>)); MethodDefinition m = new MethodDefinition($"GetSpan_{name}__Generated", MethodAttributes.Private | MethodAttributes.Static, span); ILProcessor il = m.Body.GetILProcessor(); FieldDefinition spanField = new FieldDefinition($"Span__{name}__Generated__{type.Name}", FieldAttributes.Assembly | FieldAttributes.Static | FieldAttributes.InitOnly | FieldAttributes.HasFieldRVA, GetSpanType(name.Length + 1)) { InitialValue = GetEncodedStringBytes(name) }; type.Fields.Add(spanField); il.Emit(OpCodes.Ldsflda, spanField); il.EmitInt(name.Length + 1); il.Emit(OpCodes.Newobj, module.ImportReference(typeof(ReadOnlySpan <byte>).GetConstructor(new[] { typeof(void *), typeof(int) }))); il.Emit(OpCodes.Ret); m.Body.Optimize(); type.Methods.Add(m); TypeReference GetSpanType(int nameLength) { switch (nameLength) { case 2: return(module.GetTypeReference <short>()); case 4: return(module.GetTypeReference <int>()); case 8: return(module.GetTypeReference <long>()); default: if (spanCustomTypes.TryGetValue(type, out Dictionary <int, TypeDefinition> d) && d.TryGetValue(nameLength, out TypeDefinition customSpanType)) { return(module.ImportReference(customSpanType)); } customSpanType = new TypeDefinition("", $"ALE__Generated__StaticArrayInitTypeSize={nameLength}", TypeAttributes.NestedPrivate | TypeAttributes.AnsiClass | TypeAttributes.ExplicitLayout | TypeAttributes.Sealed, module.GetTypeReference <ValueType>()); customSpanType.PackingSize = 1; customSpanType.ClassSize = nameLength; if (!spanCustomTypes.ContainsKey(type)) { spanCustomTypes.Add(type, new Dictionary <int, TypeDefinition>()); } if (!spanCustomTypes[type].ContainsKey(nameLength)) { spanCustomTypes[type].Add(nameLength, customSpanType); } type.NestedTypes.Add(customSpanType); return(module.ImportReference(customSpanType)); } } return(m); }