Example #1
0
        private static TypeInfo BuildType(Type enumType)
        {
            Type underlyingType = Enum.GetUnderlyingType(enumType);
            Type formatterType  = typeof(IMessagePackFormatter <>).MakeGenericType(enumType);

            using (MonoProtection.EnterRefEmitLock())
            {
                TypeBuilder typeBuilder = DynamicAssembly.Value.DefineType("Phoesion.MsgPack.Formatters." + enumType.FullName.Replace(".", "_") + "Formatter" + Interlocked.Increment(ref nameSequence), TypeAttributes.Public | TypeAttributes.Sealed, null, new[] { formatterType });

                // void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options);
                {
                    MethodBuilder method = typeBuilder.DefineMethod(
                        "Serialize",
                        MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
                        null,
                        new Type[] { typeof(MessagePackWriter).MakeByRefType(), enumType, typeof(MessagePackSerializerOptions) });

                    ILGenerator il = method.GetILGenerator();
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Ldarg_2);
                    il.Emit(OpCodes.Call, typeof(MessagePackWriter).GetRuntimeMethod(nameof(MessagePackWriter.Write), new[] { underlyingType }));
                    il.Emit(OpCodes.Ret);
                }

                // T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options);
                {
                    MethodBuilder method = typeBuilder.DefineMethod(
                        "Deserialize",
                        MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual,
                        enumType,
                        new Type[] { typeof(MessagePackReader).MakeByRefType(), typeof(MessagePackSerializerOptions) });

                    ILGenerator il = method.GetILGenerator();
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Call, typeof(MessagePackReader).GetRuntimeMethod("Read" + underlyingType.Name, Type.EmptyTypes));
                    il.Emit(OpCodes.Ret);
                }

                return(typeBuilder.CreateTypeInfo());
            }
        }
        private static TypeInfo BuildType(Type type)
        {
            TypeInfo ti = type.GetTypeInfo();

            // order by key(important for use jump-table of switch)
            UnionAttribute[] unionAttrs = ti.GetCustomAttributes <UnionAttribute>().OrderBy(x => x.Key).ToArray();

            if (unionAttrs.Length == 0)
            {
                return(null);
            }

            if (!ti.IsInterface && !ti.IsAbstract)
            {
                throw new MessagePackDynamicUnionResolverException("Union can only be interface or abstract class. Type:" + type.Name);
            }

            var checker1 = new HashSet <int>();
            var checker2 = new HashSet <Type>();

            foreach (UnionAttribute item in unionAttrs)
            {
                if (!checker1.Add(item.Key))
                {
                    throw new MessagePackDynamicUnionResolverException("Same union key has found. Type:" + type.Name + " Key:" + item.Key);
                }

                if (!checker2.Add(item.SubType))
                {
                    throw new MessagePackDynamicUnionResolverException("Same union subType has found. Type:" + type.Name + " SubType: " + item.SubType);
                }
            }

            Type formatterType = typeof(IMessagePackFormatter <>).MakeGenericType(type);

            using (MonoProtection.EnterRefEmitLock())
            {
                TypeBuilder typeBuilder = DynamicAssembly.Value.DefineType("Phoesion.MsgPack.Formatters." + SubtractFullNameRegex.Replace(type.FullName, string.Empty).Replace(".", "_") + "Formatter" + +Interlocked.Increment(ref nameSequence), TypeAttributes.Public | TypeAttributes.Sealed, null, new[] { formatterType });

                FieldBuilder typeToKeyAndJumpMap = null; // Dictionary<RuntimeTypeHandle, KeyValuePair<int, int>>
                FieldBuilder keyToJumpMap        = null; // Dictionary<int, int>

                // create map dictionary
                {
                    ConstructorBuilder method = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
                    typeToKeyAndJumpMap = typeBuilder.DefineField("typeToKeyAndJumpMap", typeof(Dictionary <RuntimeTypeHandle, KeyValuePair <int, int> >), FieldAttributes.Private | FieldAttributes.InitOnly);
                    keyToJumpMap        = typeBuilder.DefineField("keyToJumpMap", typeof(Dictionary <int, int>), FieldAttributes.Private | FieldAttributes.InitOnly);

                    ILGenerator il = method.GetILGenerator();
                    BuildConstructor(type, unionAttrs, method, typeToKeyAndJumpMap, keyToJumpMap, il);
                }

                {
                    MethodBuilder method = typeBuilder.DefineMethod(
                        "Serialize",
                        MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot,
                        null,
                        new Type[] { typeof(MessagePackWriter).MakeByRefType(), type, typeof(MessagePackSerializerOptions) });

                    ILGenerator il = method.GetILGenerator();
                    BuildSerialize(type, unionAttrs, method, typeToKeyAndJumpMap, il);
                }

                {
                    MethodBuilder method = typeBuilder.DefineMethod(
                        "Deserialize",
                        MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot,
                        type,
                        new Type[] { refMessagePackReader, typeof(MessagePackSerializerOptions) });

                    ILGenerator il = method.GetILGenerator();
                    BuildDeserialize(type, unionAttrs, method, keyToJumpMap, il);
                }

                return(typeBuilder.CreateTypeInfo());
            }
        }