public static void GenDeserializerCall(CodeGenContext ctx, ILGenerator il, Type type) { // We can call the Deserializer method directly for: // - Value types // - Array types // - Sealed types with static Deserializer method, as the method will handle null // Other reference types go through the DeserializesSwitch bool direct; if (type.IsValueType || type.IsArray) direct = true; else if (type.IsSealed && ctx.IsGenerated(type) == false) direct = true; else if (!ctx.HasSwitch(type)) direct = true; else direct = false; var method = direct ? ctx.GetReaderMethodInfo(type) : ctx.DeserializerSwitchMethodInfo; il.EmitCall(OpCodes.Call, method, null); }
public static void GenerateSerializerSwitchTyped(CodeGenContext ctx, ILGenerator il, IDictionary<Type, TypeData> map) { // arg0: Stream, arg1: object, arg2: ushort var idLocal = il.DeclareLocal(typeof(ushort)); // +1 for 0 (null) var jumpTable = new Label[map.Count + 1]; jumpTable[0] = il.DefineLabel(); foreach (var kvp in map) jumpTable[kvp.Value.TypeID] = il.DefineLabel(); // get TypeID from object's Type il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Switch, jumpTable); il.Emit(OpCodes.Newobj, Helpers.ExceptionCtorInfo); il.Emit(OpCodes.Throw); /* null case */ il.MarkLabel(jumpTable[0]); il.Emit(OpCodes.Ret); /* cases for types */ foreach (var kvp in map) { var type = kvp.Key; var data = kvp.Value; il.MarkLabel(jumpTable[data.TypeID]); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type); il.EmitCall(OpCodes.Call, data.WriterTypedMethodInfo, null); il.Emit(OpCodes.Ret); } }
public static void GenerateSerializerSwitch(CodeGenContext ctx, ILGenerator il, IDictionary<Type, TypeData> map) { // arg0: Stream, arg1: object var idLocal = il.DeclareLocal(typeof(ushort)); // bool ilLocal2 = Helpers.HasSwitchTypeMethodInfo(obj); var idLocal2 = il.DeclareLocal(typeof(bool)); il.Emit(OpCodes.Ldarg_1); il.EmitCall(OpCodes.Call, Helpers.HasSwitchTypeMethodInfo, null); il.Emit(OpCodes.Stloc_S, idLocal2); // get TypeID from object's Type il.Emit(OpCodes.Ldarg_1); il.EmitCall(OpCodes.Call, Helpers.GetTypeIDMethodInfo, null); il.Emit(OpCodes.Stloc_S, idLocal); var hasSwitchLabel = il.DefineLabel(); // if (idLocal2.HasSwitch) il.Emit(OpCodes.Ldloc_S, idLocal2); il.Emit(OpCodes.Brfalse_S, hasSwitchLabel); // write typeID //il.Emit(OpCodes.) il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldloc_S, idLocal); il.EmitCall(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(ushort)), null); il.MarkLabel(hasSwitchLabel); // +1 for 0 (null) var jumpTable = new Label[map.Count + 1]; jumpTable[0] = il.DefineLabel(); foreach (var kvp in map) jumpTable[kvp.Value.TypeID] = il.DefineLabel(); il.Emit(OpCodes.Ldloc_S, idLocal); il.Emit(OpCodes.Switch, jumpTable); il.Emit(OpCodes.Newobj, Helpers.ExceptionCtorInfo); il.Emit(OpCodes.Throw); /* null case */ il.MarkLabel(jumpTable[0]); il.Emit(OpCodes.Ret); /* cases for types */ foreach (var kvp in map) { var type = kvp.Key; var data = kvp.Value; il.MarkLabel(jumpTable[data.TypeID]); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type); il.EmitCall(OpCodes.Call, data.WriterMethodInfo, null); il.Emit(OpCodes.Ret); } }