Example #1
0
        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);
        }
Example #2
0
        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);
            }
        }
Example #3
0
        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);
            }
        }