private static void CreateTupleUnpackFrom(SerializerEmitter emitter, IList <Type> itemTypes) { var il = emitter.GetUnpackFromMethodILGenerator(); var localHolder = new LocalVariableHolder(il); try { /* * checked * { * if (!unpacker.IsArrayHeader) * { * throw SerializationExceptions.NewIsNotArrayHeader(); * } * * if ((int)unpacker.ItemsCount != n) * { * throw SerializationExceptions.NewTupleCardinarityIsNotMatch(n, (int)unpacker.ItemsCount); * } * * if (!unpacker.Read()) * { * throw SerializationExceptions.NewMissingItem(0); * } * * DESERIALIZE_VALUE * * : * * return new Tuple<...>( item1, ... , new Tuple<...>(...)...); * } */ il.EmitAnyLdarg(1); il.EmitGetProperty(Metadata._Unpacker.IsArrayHeader); var endIf = il.DefineLabel("END_IF"); il.EmitBrtrue_S(endIf); il.EmitAnyCall(SerializationExceptions.NewIsNotArrayHeaderMethod); il.EmitThrow(); il.MarkLabel(endIf); var itemsCount = localHolder.ItemsCount; Emittion.EmitGetUnpackerItemsCountAsInt32(il, 1, localHolder); il.EmitAnyLdc_I4(itemTypes.Count); il.EmitAnyStloc(itemsCount); il.EmitAnyLdloc(itemsCount); var endIf1 = il.DefineLabel("END_IF1"); il.EmitBeq_S(endIf1); il.EmitAnyLdc_I4(itemTypes.Count); il.EmitAnyLdloc(itemsCount); il.EmitAnyCall(SerializationExceptions.NewTupleCardinarityIsNotMatchMethod); il.EmitThrow(); il.MarkLabel(endIf1); var itemLocals = new LocalBuilder[itemTypes.Count]; var useDummyNullables = new bool[itemTypes.Count]; for (int i = 0; i < itemTypes.Count; i++) { if (itemTypes[i] != typeof(MessagePackObject) && itemTypes[i].GetIsValueType() && Nullable.GetUnderlyingType(itemTypes[i]) == null) { // Use temporary nullable value for nil implication. itemLocals[i] = il.DeclareLocal(typeof(Nullable <>).MakeGenericType(itemTypes[i]), "item" + i.ToString(CultureInfo.InvariantCulture)); useDummyNullables[i] = true; } else { itemLocals[i] = il.DeclareLocal(itemTypes[i], "item" + i.ToString(CultureInfo.InvariantCulture)); } // Tuple member should be NilImplication.MemberDefault. Emittion.EmitDeserializeValueWithoutNilImplication(emitter, il, 1, itemLocals[i], typeof(Tuple), "Item" + (i).ToString(CultureInfo.InvariantCulture), localHolder); } for (int i = 0; i < itemLocals.Length; i++) { if (useDummyNullables[i]) { il.EmitAnyLdloca(itemLocals[i]); il.EmitGetProperty(typeof(Nullable <>).MakeGenericType(itemTypes[i]).GetProperty("Value")); } else { il.EmitAnyLdloc(itemLocals[i]); } } var tupleTypeList = TupleItems.CreateTupleTypeList(itemTypes); for (int depth = tupleTypeList.Count - 1; 0 <= depth; depth--) { il.EmitNewobj(tupleTypeList[depth].GetConstructors().Single()); } il.EmitRet(); } finally { il.FlushTrace(); } }