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