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.GetTypeInfo().IsInterface)
{
switch (collectionContract.Kind)
{
case CollectionKind.GenericDictionary:
type = Globals.TypeOfDictionaryGeneric.MakeGenericType(itemType.GetGenericArguments());
constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Array.Empty<Type>());
break;
case CollectionKind.Dictionary:
type = Globals.TypeOfHashtable;
constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, Array.Empty<Type>());
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;
}
}
_objectLocal = _ilg.DeclareLocal(type, "objectDeserialized");
if (!isArray)
{
if (type.GetTypeInfo().IsValueType)
{
_ilg.Ldloca(_objectLocal);
_ilg.InitObj(type);
}
else
{
_ilg.New(constructor);
_ilg.Stloc(_objectLocal);
_ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, _objectLocal);
}
}
bool canReadSimpleDictionary = collectionContract.Kind == CollectionKind.Dictionary ||
collectionContract.Kind == CollectionKind.GenericDictionary;
if (canReadSimpleDictionary)
{
_ilg.Load(_contextArg);
_ilg.LoadMember(JsonFormatGeneratorStatics.UseSimpleDictionaryFormatReadProperty);
_ilg.If();
ReadSimpleDictionary(collectionContract, itemType);
_ilg.Else();
}
LocalBuilder objectId = _ilg.DeclareLocal(Globals.TypeOfString, "objectIdRead");
_ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetObjectIdMethod);
_ilg.Stloc(objectId);
bool canReadPrimitiveArray = false;
if (isArray && TryReadPrimitiveArray(itemType))
{
canReadPrimitiveArray = true;
_ilg.IfNot();
}
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, Int32.MaxValue);
// Empty namespace
IsStartElement(_memberNamesArg, _emptyDictionaryStringArg);
_ilg.If();
_ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1);
LocalBuilder value = ReadCollectionItem(collectionContract, itemType);
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);
}
if (canReadPrimitiveArray)
{
_ilg.Else();
_ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectWithIdMethod, objectId, _objectLocal);
_ilg.EndIf();
}
if (canReadSimpleDictionary)
{
_ilg.EndIf();
}
}