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);
        }
예제 #2
0
        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);
        }