Esempio n. 1
0
        public static bool TryEmitDeserialiseCode(ILGenerator ilg, ThrowBlockGatherer throwBlocks, ICollection <string> errors, string name, Type targetType, LocalBuilder value, LocalBuilder unpacker, DasherContext context, LocalBuilder contextLocal, UnexpectedFieldBehaviour unexpectedFieldBehaviour, bool isRoot = false)
        {
            if (!context.TryGetTypeProvider(value.LocalType, errors, out ITypeProvider provider))
            {
                return(false);
            }

            if (!isRoot && provider is ComplexTypeProvider)
            {
                ilg.Emit(OpCodes.Ldloc, contextLocal);
                ilg.LoadType(value.LocalType);
                ilg.Emit(OpCodes.Ldc_I4, (int)unexpectedFieldBehaviour);
                ilg.Emit(OpCodes.Call, Methods.DasherContext_GetOrCreateDeserialiseFunc);
                ilg.Emit(OpCodes.Ldloc, unpacker);
                ilg.Emit(OpCodes.Ldloc, contextLocal);
                ilg.Emit(OpCodes.Call, Methods.DasherDeserialiseFunc_Invoke);
                ilg.Emit(value.LocalType.GetTypeInfo().IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, value.LocalType);
                ilg.Emit(OpCodes.Stloc, value);
            }
            else
            {
                var end = ilg.DefineLabel();

                if (provider.UseDefaultNullHandling(value.LocalType))
                {
                    // check for null
                    var nonNullLabel = ilg.DefineLabel();
                    ilg.Emit(OpCodes.Ldloc, unpacker);
                    ilg.Emit(OpCodes.Call, Methods.Unpacker_TryReadNull);
                    ilg.Emit(OpCodes.Brfalse_S, nonNullLabel);
                    {
                        ilg.Emit(OpCodes.Ldnull);
                        ilg.Emit(OpCodes.Stloc, value);
                        ilg.Emit(OpCodes.Br, end);
                    }
                    ilg.MarkLabel(nonNullLabel);
                }

                if (!provider.TryEmitDeserialiseCode(ilg, throwBlocks, errors, name, targetType, value, unpacker, contextLocal, context, unexpectedFieldBehaviour))
                {
                    return(false);
                }

                ilg.MarkLabel(end);
            }
            return(true);
        }
Esempio n. 2
0
        public static bool TryEmitSerialiseCode(ILGenerator ilg, ThrowBlockGatherer throwBlocks, ICollection <string> errors, LocalBuilder value, LocalBuilder packer, DasherContext context, LocalBuilder contextLocal, bool isRoot = false)
        {
            if (!context.TryGetTypeProvider(value.LocalType, errors, out ITypeProvider provider))
            {
                return(false);
            }

            if (!isRoot && provider is ComplexTypeProvider)
            {
                // prevent endless code generation for recursive types by delegating to a method call
                ilg.Emit(OpCodes.Ldloc, contextLocal);
                ilg.LoadType(value.LocalType);
                ilg.Emit(OpCodes.Call, Methods.DasherContext_GetOrCreateSerialiseAction);

                ilg.Emit(OpCodes.Ldloc, packer);
                ilg.Emit(OpCodes.Ldloc, contextLocal);
                ilg.Emit(OpCodes.Ldloc, value);
                if (value.LocalType.GetTypeInfo().IsValueType)
                {
                    ilg.Emit(OpCodes.Box, value.LocalType);
                }
                ilg.Emit(OpCodes.Call, Methods.DasherSerialiseAction_Invoke);
            }
            else
            {
                var end = ilg.DefineLabel();

                if (provider.UseDefaultNullHandling(value.LocalType))
                {
                    var nonNull = ilg.DefineLabel();
                    ilg.Emit(OpCodes.Ldloc, value);
                    ilg.Emit(OpCodes.Brtrue_S, nonNull);
                    ilg.Emit(OpCodes.Ldloc, packer);
                    ilg.Emit(OpCodes.Call, Methods.Packer_PackNull);
                    ilg.Emit(OpCodes.Br, end);
                    ilg.MarkLabel(nonNull);
                }

                if (!provider.TryEmitSerialiseCode(ilg, throwBlocks, errors, value, packer, contextLocal, context))
                {
                    return(false);
                }

                ilg.MarkLabel(end);
            }
            return(true);
        }