private void ReadCollection(CollectionDataContract collectionContract) { Type type = collectionContract.UnderlyingType; Type itemType = collectionContract.ItemType; bool isArray = (collectionContract.Kind == CollectionKind.Array); ConstructorInfo constructor = collectionContract.Constructor; if (type.IsInterface) { switch (collectionContract.Kind) { case CollectionKind.GenericDictionary: type = Globals.TypeOfDictionaryGeneric.MakeGenericType(itemType.GetGenericArguments()); constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public, Array.Empty <Type>()); break; case CollectionKind.Dictionary: type = Globals.TypeOfHashtable; constructor = XmlFormatGeneratorStatics.HashtableCtor; break; case CollectionKind.Collection: case CollectionKind.GenericCollection: case CollectionKind.Enumerable: case CollectionKind.GenericEnumerable: case CollectionKind.List: case CollectionKind.GenericList: type = itemType.MakeArrayType(); isArray = true; break; } } string itemName = collectionContract.ItemName; string itemNs = collectionContract.StableName.Namespace; _objectLocal = _ilg.DeclareLocal(type, "objectDeserialized"); if (!isArray) { if (type.IsValueType) { _ilg.Ldloca(_objectLocal); _ilg.InitObj(type); } else { _ilg.New(constructor); _ilg.Stloc(_objectLocal); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, _objectLocal); } } LocalBuilder size = _ilg.DeclareLocal(Globals.TypeOfInt, "arraySize"); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetArraySizeMethod); _ilg.Stloc(size); LocalBuilder objectId = _ilg.DeclareLocal(Globals.TypeOfString, "objectIdRead"); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetObjectIdMethod); _ilg.Stloc(objectId); bool canReadPrimitiveArray = false; if (isArray && TryReadPrimitiveArray(type, itemType, size)) { canReadPrimitiveArray = true; _ilg.IfNot(); } _ilg.If(size, Cmp.EqualTo, -1); LocalBuilder growingCollection = null; if (isArray) { growingCollection = _ilg.DeclareLocal(type, "growingCollection"); _ilg.NewArray(itemType, 32); _ilg.Stloc(growingCollection); } LocalBuilder i = _ilg.DeclareLocal(Globals.TypeOfInt, "i"); object forLoop = _ilg.For(i, 0, int.MaxValue); IsStartElement(_memberNamesArg, _memberNamespacesArg); _ilg.If(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1); LocalBuilder value = ReadCollectionItem(collectionContract, itemType, itemName, itemNs); if (isArray) { MethodInfo ensureArraySizeMethod = XmlFormatGeneratorStatics.EnsureArraySizeMethod.MakeGenericMethod(itemType); _ilg.Call(null, ensureArraySizeMethod, growingCollection, i); _ilg.Stloc(growingCollection); _ilg.StoreArrayElement(growingCollection, i, value); } else { StoreCollectionValue(_objectLocal, value, collectionContract); } _ilg.Else(); IsEndElement(); _ilg.If(); _ilg.Break(forLoop); _ilg.Else(); HandleUnexpectedItemInCollection(i); _ilg.EndIf(); _ilg.EndIf(); _ilg.EndFor(); if (isArray) { MethodInfo trimArraySizeMethod = XmlFormatGeneratorStatics.TrimArraySizeMethod.MakeGenericMethod(itemType); _ilg.Call(null, trimArraySizeMethod, growingCollection, i); _ilg.Stloc(_objectLocal); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectWithIdMethod, objectId, _objectLocal); } _ilg.Else(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, size); if (isArray) { _ilg.NewArray(itemType, size); _ilg.Stloc(_objectLocal); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, _objectLocal); } LocalBuilder j = _ilg.DeclareLocal(Globals.TypeOfInt, "j"); _ilg.For(j, 0, size); IsStartElement(_memberNamesArg, _memberNamespacesArg); _ilg.If(); LocalBuilder itemValue = ReadCollectionItem(collectionContract, itemType, itemName, itemNs); if (isArray) { _ilg.StoreArrayElement(_objectLocal, j, itemValue); } else { StoreCollectionValue(_objectLocal, itemValue, collectionContract); } _ilg.Else(); HandleUnexpectedItemInCollection(j); _ilg.EndIf(); _ilg.EndFor(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.CheckEndOfArrayMethod, _xmlReaderArg, size, _memberNamesArg, _memberNamespacesArg); _ilg.EndIf(); if (canReadPrimitiveArray) { _ilg.Else(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectWithIdMethod, objectId, _objectLocal); _ilg.EndIf(); } }