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()); } }