public static List<object> ConvertGenericDictionaryToArray(DataContractJsonSerializer serializer, IEnumerable value, CollectionDataContract dataContract, XmlObjectSerializerWriteContextComplexJson context, bool writeServerType) { List<object> keyValuePair = new List<object>(); Dictionary<string, object> currentEntry; Type[] declaredTypes = dataContract.ItemType.GetGenericArguments(); MethodInfo getEnumeratorMethod = dataContract.GetEnumeratorMethod; IDictionaryEnumerator enumerator = (IDictionaryEnumerator)((getEnumeratorMethod == null) ? value.GetEnumerator() : (IDictionaryEnumerator)getEnumeratorMethod.Invoke(value, Array.Empty<Type>())); while (enumerator.MoveNext()) { DictionaryEntry current = enumerator.Entry; DataContract currentDataContract = DataContract.GetDataContract(enumerator.Current.GetType()); currentEntry = new Dictionary<string, object>(); if (writeServerType) { AddTypeInformation(currentEntry, currentDataContract); } context.PushKnownTypes(dataContract); AddDictionaryEntryData(serializer, currentEntry, writeServerType ? JsonGlobals.KeyString.ToLowerInvariant() : JsonGlobals.KeyString, declaredTypes[0], current.Key, context); AddDictionaryEntryData(serializer, currentEntry, writeServerType ? JsonGlobals.ValueString.ToLowerInvariant() : JsonGlobals.ValueString, declaredTypes[1], current.Value, context); keyValuePair.Add(currentEntry); context.PopKnownTypes(dataContract); } return keyValuePair; }
public static IEnumerable ConvertGenericListToArray(DataContractJsonSerializer serializer, IEnumerable value, CollectionDataContract dataContract, XmlObjectSerializerWriteContextComplexJson context, bool writeServerType) { Type listArgumentType = dataContract.ItemType; if (listArgumentType.GetTypeInfo().IsGenericType) { listArgumentType = listArgumentType.GetGenericArguments()[0]; } List<object> serializedList = new List<object>(); MethodInfo getEnumeratorMethod = dataContract.GetEnumeratorMethod; IEnumerator enumerator = (getEnumeratorMethod == null) ? value.GetEnumerator() : (IEnumerator)getEnumeratorMethod.Invoke(value, Array.Empty<Type>()); while (enumerator.MoveNext()) { if (enumerator.Current == null || enumerator.Current.GetType().GetTypeInfo().IsPrimitive) { serializedList.Add(enumerator.Current); } else { Type currentItemType = enumerator.Current.GetType(); DataContract currentItemDataContract = DataContract.GetDataContract(currentItemType); bool emitTypeInformation = EmitTypeInformation(dataContract.ItemContract, currentItemType); if (writeServerType || emitTypeInformation) { context.CheckIfTypeNeedsVerifcation(dataContract.ItemContract, currentItemDataContract); } context.PushKnownTypes(dataContract); serializedList.Add(serializer.ConvertDataContractToObject(enumerator.Current, currentItemDataContract, context, (writeServerType || emitTypeInformation), dataContract.ItemType.TypeHandle)); context.PopKnownTypes(dataContract); } } return serializedList; }
public void WriteCollectionToJson (XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContextComplexJson context, CollectionDataContract dataContract) { this.writer = xmlWriter; this.obj = obj; this.context = context; this.dataContract = dataContract; InitArgs (collectionContract.UnderlyingType); // DemandMemberAccessPermission(memberAccessFlag); if (collectionContract.IsReadOnlyContract) { DataContract.ThrowInvalidDataContractException (collectionContract.SerializationExceptionMessage, null); } WriteCollection (collectionContract); }
public XmlFormatGetOnlyCollectionReaderDelegate GenerateGetOnlyCollectionReader(CollectionDataContract collectionContract) { try { if (TD.DCGenReaderStartIsEnabled()) { TD.DCGenReaderStart("GetOnlyCollection", collectionContract.UnderlyingType.FullName); } return helper.GenerateGetOnlyCollectionReader(collectionContract); } finally { if (TD.DCGenReaderStopIsEnabled()) { TD.DCGenReaderStop(); } } }
internal JsonFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract) { try { if (TD.DCJsonGenWriterStartIsEnabled()) { TD.DCJsonGenWriterStart("Collection", collectionContract.UnderlyingType.FullName); } return helper.GenerateCollectionWriter(collectionContract); } finally { if (TD.DCJsonGenWriterStopIsEnabled()) { TD.DCJsonGenWriterStop(); } } }
public JsonFormatCollectionReaderDelegate GenerateCollectionReader(CollectionDataContract collectionContract) { try { if (TD.DCJsonGenReaderStartIsEnabled()) { TD.DCJsonGenReaderStart("Collection", collectionContract.StableName.Name); } return helper.GenerateCollectionReader(collectionContract); } finally { if (TD.DCJsonGenReaderStopIsEnabled()) { TD.DCJsonGenReaderStop(); } } }
internal JsonFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract) { _ilg = new CodeGenerator(); bool memberAccessFlag = collectionContract.RequiresMemberAccessForWrite(null); try { BeginMethod(_ilg, "Write" + DataContract.SanitizeTypeName(collectionContract.StableName.Name) + "ToJson", typeof(JsonFormatCollectionWriterDelegate), memberAccessFlag); } catch (SecurityException securityException) { if (memberAccessFlag) { collectionContract.RequiresMemberAccessForWrite(securityException); } else { throw; } } InitArgs(collectionContract.UnderlyingType); WriteCollection(collectionContract); return (JsonFormatCollectionWriterDelegate)_ilg.EndMethod(); }
internal static DataContract GetDataContractFromSurrogateSelector(ISurrogateSelector surrogateSelector, StreamingContext context, RuntimeTypeHandle typeHandle, Type type, ref Hashtable surrogateDataContracts) { if (surrogateSelector == null) return null; if (type == null) type = Type.GetTypeFromHandle(typeHandle); DataContract builtInDataContract = DataContract.GetBuiltInDataContract(type); if (builtInDataContract != null) return builtInDataContract; if (surrogateDataContracts != null) { DataContract cachedSurrogateContract = (DataContract)surrogateDataContracts[type]; if (cachedSurrogateContract != null) return cachedSurrogateContract; } DataContract surrogateContract = null; ISerializationSurrogate surrogate = GetSurrogate(type, surrogateSelector, context); if (surrogate != null) surrogateContract = new SurrogateDataContract(type, surrogate); else if (type.IsArray) { Type elementType = type.GetElementType(); DataContract itemContract = GetDataContractFromSurrogateSelector(surrogateSelector, context, elementType.TypeHandle, elementType, ref surrogateDataContracts); if (itemContract == null) itemContract = DataContract.GetDataContract(elementType.TypeHandle, elementType, SerializationMode.SharedType); surrogateContract = new CollectionDataContract(type, itemContract); } if (surrogateContract != null) { if (surrogateDataContracts == null) surrogateDataContracts = new Hashtable(); surrogateDataContracts.Add(type, surrogateContract); return surrogateContract; } return null; }
public JsonFormatGetOnlyCollectionReaderDelegate GenerateGetOnlyCollectionReader(CollectionDataContract collectionContract) { return _helper.GenerateGetOnlyCollectionReader(collectionContract); }
void StoreCollectionValue(LocalBuilder collection, LocalBuilder value, CollectionDataContract collectionContract) { if (collectionContract.Kind == CollectionKind.GenericDictionary || collectionContract.Kind == CollectionKind.Dictionary) { ClassDataContract keyValuePairContract = DataContract.GetDataContract(value.LocalType) as ClassDataContract; if (keyValuePairContract == null) { Fx.Assert("Failed to create contract for KeyValuePair type"); } DataMember keyMember = keyValuePairContract.Members[0]; DataMember valueMember = keyValuePairContract.Members[1]; LocalBuilder pairKey = ilg.DeclareLocal(keyMember.MemberType, keyMember.Name); LocalBuilder pairValue = ilg.DeclareLocal(valueMember.MemberType, valueMember.Name); ilg.LoadAddress(value); ilg.LoadMember(keyMember.MemberInfo); ilg.Stloc(pairKey); ilg.LoadAddress(value); ilg.LoadMember(valueMember.MemberInfo); ilg.Stloc(pairValue); ilg.Call(collection, collectionContract.AddMethod, pairKey, pairValue); if (collectionContract.AddMethod.ReturnType != Globals.TypeOfVoid) ilg.Pop(); } else { ilg.Call(collection, collectionContract.AddMethod, value); if (collectionContract.AddMethod.ReturnType != Globals.TypeOfVoid) ilg.Pop(); } }
void WriteCollection(CollectionDataContract collectionContract) { LocalBuilder itemName = ilg.DeclareLocal(typeof(XmlDictionaryString), "itemName"); ilg.Load(contextArg); ilg.LoadMember(JsonFormatGeneratorStatics.CollectionItemNameProperty); ilg.Store(itemName); if (collectionContract.Kind == CollectionKind.Array) { Type itemType = collectionContract.ItemType; LocalBuilder i = ilg.DeclareLocal(Globals.TypeOfInt, "i"); ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementArrayCountMethod, xmlWriterArg, objectLocal); if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, objectLocal, itemName)) { WriteArrayAttribute(); ilg.For(i, 0, objectLocal); if (!TryWritePrimitive(itemType, null /*value*/, null /*memberInfo*/, i /*arrayItemIndex*/, itemName, 0 /*nameIndex*/)) { WriteStartElement(itemName, 0 /*nameIndex*/); ilg.LoadArrayElement(objectLocal, i); LocalBuilder memberValue = ilg.DeclareLocal(itemType, "memberValue"); ilg.Stloc(memberValue); WriteValue(memberValue); WriteEndElement(); } ilg.EndFor(); } } else { MethodInfo incrementCollectionCountMethod = null; switch (collectionContract.Kind) { case CollectionKind.Collection: case CollectionKind.List: case CollectionKind.Dictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod; break; case CollectionKind.GenericCollection: case CollectionKind.GenericList: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType); break; case CollectionKind.GenericDictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments())); break; } if (incrementCollectionCountMethod != null) { ilg.Call(contextArg, incrementCollectionCountMethod, xmlWriterArg, objectLocal); } bool isDictionary = false, isGenericDictionary = false; Type enumeratorType = null; Type[] keyValueTypes = null; if (collectionContract.Kind == CollectionKind.GenericDictionary) { isGenericDictionary = true; keyValueTypes = collectionContract.ItemType.GetGenericArguments(); enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType(keyValueTypes); } else if (collectionContract.Kind == CollectionKind.Dictionary) { isDictionary = true; keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject }; enumeratorType = Globals.TypeOfDictionaryEnumerator; } else { enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType; } MethodInfo moveNextMethod = enumeratorType.GetMethod(Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); MethodInfo getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); if (moveNextMethod == null || getCurrentMethod == null) { if (enumeratorType.IsInterface) { if (moveNextMethod == null) moveNextMethod = JsonFormatGeneratorStatics.MoveNextMethod; if (getCurrentMethod == null) getCurrentMethod = JsonFormatGeneratorStatics.GetCurrentMethod; } else { Type ienumeratorInterface = Globals.TypeOfIEnumerator; CollectionKind kind = collectionContract.Kind; if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable) { Type[] interfaceTypes = enumeratorType.GetInterfaces(); foreach (Type interfaceType in interfaceTypes) { if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric && interfaceType.GetGenericArguments()[0] == collectionContract.ItemType) { ienumeratorInterface = interfaceType; break; } } } if (moveNextMethod == null) moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface); if (getCurrentMethod == null) getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface); } } Type elementType = getCurrentMethod.ReturnType; LocalBuilder currentValue = ilg.DeclareLocal(elementType, "currentValue"); LocalBuilder enumerator = ilg.DeclareLocal(enumeratorType, "enumerator"); ilg.Call(objectLocal, collectionContract.GetEnumeratorMethod); if (isDictionary) { ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { Globals.TypeOfIDictionaryEnumerator }, null); ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, Globals.TypeOfIDictionaryEnumerator); ilg.New(dictEnumCtor); } else if (isGenericDictionary) { Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes)); ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null); ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, ctorParam); ilg.New(dictEnumCtor); } ilg.Stloc(enumerator); bool canWriteSimpleDictionary = isDictionary || isGenericDictionary; if (canWriteSimpleDictionary) { Type genericDictionaryKeyValueType = Globals.TypeOfKeyValue.MakeGenericType(keyValueTypes); PropertyInfo genericDictionaryKeyProperty = genericDictionaryKeyValueType.GetProperty(JsonGlobals.KeyString); PropertyInfo genericDictionaryValueProperty = genericDictionaryKeyValueType.GetProperty(JsonGlobals.ValueString); ilg.Load(contextArg); ilg.LoadMember(JsonFormatGeneratorStatics.UseSimpleDictionaryFormatWriteProperty); ilg.If(); WriteObjectAttribute(); LocalBuilder pairKey = ilg.DeclareLocal(Globals.TypeOfString, "key"); LocalBuilder pairValue = ilg.DeclareLocal(keyValueTypes[1], "value"); ilg.ForEach(currentValue, elementType, enumeratorType, enumerator, getCurrentMethod); ilg.LoadAddress(currentValue); ilg.LoadMember(genericDictionaryKeyProperty); ilg.ToString(keyValueTypes[0]); ilg.Stloc(pairKey); ilg.LoadAddress(currentValue); ilg.LoadMember(genericDictionaryValueProperty); ilg.Stloc(pairValue); WriteStartElement(pairKey, 0 /*nameIndex*/); WriteValue(pairValue); WriteEndElement(); ilg.EndForEach(moveNextMethod); ilg.Else(); } WriteArrayAttribute(); ilg.ForEach(currentValue, elementType, enumeratorType, enumerator, getCurrentMethod); if (incrementCollectionCountMethod == null) { ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1); } if (!TryWritePrimitive(elementType, currentValue, null /*memberInfo*/, null /*arrayItemIndex*/, itemName, 0 /*nameIndex*/)) { WriteStartElement(itemName, 0 /*nameIndex*/); if (isGenericDictionary || isDictionary) { ilg.Call(dataContractArg, JsonFormatGeneratorStatics.GetItemContractMethod); ilg.Call(JsonFormatGeneratorStatics.GetRevisedItemContractMethod); ilg.Call(JsonFormatGeneratorStatics.GetJsonDataContractMethod); ilg.Load(xmlWriterArg); ilg.Load(currentValue); ilg.ConvertValue(currentValue.LocalType, Globals.TypeOfObject); ilg.Load(contextArg); ilg.Load(currentValue.LocalType); ilg.LoadMember(JsonFormatGeneratorStatics.TypeHandleProperty); ilg.Call(JsonFormatGeneratorStatics.WriteJsonValueMethod); } else { WriteValue(currentValue); } WriteEndElement(); } ilg.EndForEach(moveNextMethod); if (canWriteSimpleDictionary) { ilg.EndIf(); } } }
void ReadSimpleDictionary(CollectionDataContract collectionContract, Type keyValueType) { Type[] keyValueTypes = keyValueType.GetGenericArguments(); Type keyType = keyValueTypes[0]; Type valueType = keyValueTypes[1]; int keyTypeNullableDepth = 0; Type keyTypeOriginal = keyType; while (keyType.IsGenericType && keyType.GetGenericTypeDefinition() == Globals.TypeOfNullable) { keyTypeNullableDepth++; keyType = keyType.GetGenericArguments()[0]; } ClassDataContract keyValueDataContract = (ClassDataContract)collectionContract.ItemContract; DataContract keyDataContract = keyValueDataContract.Members[0].MemberTypeContract; KeyParseMode keyParseMode = KeyParseMode.Fail; if (keyType == Globals.TypeOfString || keyType == Globals.TypeOfObject) { keyParseMode = KeyParseMode.AsString; } else if (keyType.IsEnum) { keyParseMode = KeyParseMode.UsingParseEnum; } else if (keyDataContract.ParseMethod != null) { keyParseMode = KeyParseMode.UsingCustomParse; } if (keyParseMode == KeyParseMode.Fail) { ThrowSerializationException( SR.GetString( SR.KeyTypeCannotBeParsedInSimpleDictionary, DataContract.GetClrTypeFullName(collectionContract.UnderlyingType), DataContract.GetClrTypeFullName(keyType))); } else { LocalBuilder nodeType = ilg.DeclareLocal(typeof(XmlNodeType), "nodeType"); ilg.BeginWhileCondition(); ilg.Call(xmlReaderArg, JsonFormatGeneratorStatics.MoveToContentMethod); ilg.Stloc(nodeType); ilg.Load(nodeType); ilg.Load(XmlNodeType.EndElement); ilg.BeginWhileBody(Cmp.NotEqualTo); ilg.Load(nodeType); ilg.Load(XmlNodeType.Element); ilg.If(Cmp.NotEqualTo); ThrowUnexpectedStateException(XmlNodeType.Element); ilg.EndIf(); ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1); if (keyParseMode == KeyParseMode.UsingParseEnum) { ilg.Load(keyType); } ilg.Load(xmlReaderArg); ilg.Call(JsonFormatGeneratorStatics.GetJsonMemberNameMethod); if (keyParseMode == KeyParseMode.UsingParseEnum) { ilg.Call(JsonFormatGeneratorStatics.ParseEnumMethod); ilg.ConvertValue(Globals.TypeOfObject, keyType); } else if (keyParseMode == KeyParseMode.UsingCustomParse) { ilg.Call(keyDataContract.ParseMethod); } LocalBuilder pairKey = ilg.DeclareLocal(keyType, "key"); ilg.Stloc(pairKey); if (keyTypeNullableDepth > 0) { LocalBuilder pairKeyNullable = ilg.DeclareLocal(keyTypeOriginal, "keyOriginal"); WrapNullableObject(pairKey, pairKeyNullable, keyTypeNullableDepth); pairKey = pairKeyNullable; } LocalBuilder pairValue = ReadValue(valueType, String.Empty); StoreKeyValuePair(objectLocal, collectionContract, pairKey, pairValue); ilg.EndWhile(); } }
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, null, Globals.EmptyTypeArray, null); 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, Int32.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(); } }
private void ReadSimpleDictionary(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, CollectionDataContract collectionContract, Type keyValueType, object dictionary) { Type[] keyValueTypes = keyValueType.GetGenericArguments(); Type keyType = keyValueTypes[0]; Type valueType = keyValueTypes[1]; int keyTypeNullableDepth = 0; Type keyTypeOriginal = keyType; while (keyType.IsGenericType && keyType.GetGenericTypeDefinition() == Globals.TypeOfNullable) { keyTypeNullableDepth++; keyType = keyType.GetGenericArguments()[0]; } ClassDataContract keyValueDataContract = (ClassDataContract)collectionContract.ItemContract; DataContract keyDataContract = keyValueDataContract.Members[0].MemberTypeContract; KeyParseMode keyParseMode = KeyParseMode.Fail; if (keyType == Globals.TypeOfString || keyType == Globals.TypeOfObject) { keyParseMode = KeyParseMode.AsString; } else if (keyType.IsEnum) { keyParseMode = KeyParseMode.UsingParseEnum; } else if (keyDataContract.ParseMethod != null) { keyParseMode = KeyParseMode.UsingCustomParse; } if (keyParseMode == KeyParseMode.Fail) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new InvalidOperationException( SR.Format(SR.KeyTypeCannotBeParsedInSimpleDictionary, DataContract.GetClrTypeFullName(collectionContract.UnderlyingType), DataContract.GetClrTypeFullName(keyType)) )); } while (true) { XmlNodeType nodeType = xmlReader.MoveToContent(); if (nodeType == XmlNodeType.EndElement) { return; } if (nodeType != XmlNodeType.Element) { throw XmlObjectSerializerReadContext.CreateUnexpectedStateException(XmlNodeType.Element, xmlReader); } context.IncrementItemCount(1); string keyString = XmlObjectSerializerReadContextComplexJson.GetJsonMemberName(xmlReader); object pairKey; if (keyParseMode == KeyParseMode.UsingParseEnum) { pairKey = Enum.Parse(keyType, keyString); } else if (keyParseMode == KeyParseMode.UsingCustomParse) { pairKey = keyDataContract.ParseMethod.Invoke(null, new object[] { keyString }); } else { pairKey = keyString; } if (keyTypeNullableDepth > 0) { throw new NotImplementedException("keyTypeNullableDepth > 0"); } object pairValue = ReflectionReadValue(xmlReader, context, valueType, string.Empty, string.Empty); ((IDictionary)dictionary).Add(pairKey, pairValue); } }
public JsonFormatWriterInterpreter (CollectionDataContract collectionContract) { this.collectionContract = collectionContract; }
protected virtual void SerializeWithXsiType(XmlWriterDelegator xmlWriter, object obj, RuntimeTypeHandle objectTypeHandle, Type objectType, int declaredTypeID, RuntimeTypeHandle declaredTypeHandle, Type declaredType) { bool verifyKnownType = false; #if !NET_NATIVE DataContract dataContract; if (declaredType.GetTypeInfo().IsInterface&& CollectionDataContract.IsCollectionInterface(declaredType)) { dataContract = GetDataContractSkipValidation(DataContract.GetId(objectTypeHandle), objectTypeHandle, objectType); if (OnHandleIsReference(xmlWriter, dataContract, obj)) { return; } dataContract = GetDataContract(declaredTypeHandle, declaredType); #else DataContract dataContract = DataContract.GetDataContractFromGeneratedAssembly(declaredType); if (dataContract.TypeIsInterface && dataContract.TypeIsCollectionInterface) { if (OnHandleIsReference(xmlWriter, dataContract, obj)) { return; } if (this.Mode == SerializationMode.SharedType && dataContract.IsValidContract(this.Mode)) { dataContract = dataContract.GetValidContract(this.Mode); } else { dataContract = GetDataContract(declaredTypeHandle, declaredType); } #endif if (!WriteClrTypeInfo(xmlWriter, dataContract) && DataContractResolver != null) { if (objectType == null) { objectType = Type.GetTypeFromHandle(objectTypeHandle); } WriteResolvedTypeInfo(xmlWriter, objectType, declaredType); } } else if (declaredType.IsArray)//Array covariance is not supported in XSD. If declared type is array do not write xsi:type. Instead write xsi:type for each item { // A call to OnHandleIsReference is not necessary here -- arrays cannot be IsReference dataContract = GetDataContract(objectTypeHandle, objectType); WriteClrTypeInfo(xmlWriter, dataContract); dataContract = GetDataContract(declaredTypeHandle, declaredType); } else { dataContract = GetDataContract(objectTypeHandle, objectType); if (OnHandleIsReference(xmlWriter, dataContract, obj)) { return; } if (!WriteClrTypeInfo(xmlWriter, dataContract)) { DataContract declaredTypeContract = (declaredTypeID >= 0) ? GetDataContract(declaredTypeID, declaredTypeHandle) : GetDataContract(declaredTypeHandle, declaredType); verifyKnownType = WriteTypeInfo(xmlWriter, dataContract, declaredTypeContract); } } SerializeAndVerifyType(dataContract, xmlWriter, obj, verifyKnownType, declaredTypeHandle, declaredType); }
protected override bool ReflectionReadSpecialCollection(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, CollectionDataContract collectionContract, object resultCollection) { var jsonContext = context as XmlObjectSerializerReadContextComplexJson; Debug.Assert(jsonContext != null); bool canReadSimpleDictionary = collectionContract.Kind == CollectionKind.Dictionary || collectionContract.Kind == CollectionKind.GenericDictionary; if (canReadSimpleDictionary && jsonContext.UseSimpleDictionaryFormat) { ReadSimpleDictionary(xmlReader, context, collectionContract, collectionContract.ItemType, resultCollection); } return(false); }
public void WriteCollectionToXml(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context, CollectionDataContract collectionContract) { this.writer = xmlWriter; this.obj = obj; this.ctx = context; this.dataContract = collectionContract; InitArgs(collectionContract.UnderlyingType); // DemandMemberAccessPermission(memberAccessFlag); if (collectionContract.IsReadOnlyContract) { DataContract.ThrowInvalidDataContractException(collectionContract.SerializationExceptionMessage, null); } WriteCollection(collectionContract); }
public XmlFormatWriterInterpreter(CollectionDataContract collectionContract) { this.collectionContract = collectionContract; }
internal XmlFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract) { return((XmlWriterDelegator xw, object obj, XmlObjectSerializerWriteContext ctx, CollectionDataContract ctr) => new XmlFormatWriterInterpreter(collectionContract).WriteCollectionToXml(xw, obj, ctx, ctr)); }
private void ReadGetOnlyCollection(CollectionDataContract collectionContract) { Type type = collectionContract.UnderlyingType; Type itemType = collectionContract.ItemType; bool isArray = (collectionContract.Kind == CollectionKind.Array); LocalBuilder size = _ilg.DeclareLocal(Globals.TypeOfInt, "arraySize"); _objectLocal = _ilg.DeclareLocal(type, "objectDeserialized"); _ilg.Load(_contextArg); _ilg.LoadMember(XmlFormatGeneratorStatics.GetCollectionMemberMethod); _ilg.ConvertValue(Globals.TypeOfObject, type); _ilg.Stloc(_objectLocal); bool canReadSimpleDictionary = collectionContract.Kind == CollectionKind.Dictionary || collectionContract.Kind == CollectionKind.GenericDictionary; if (canReadSimpleDictionary) { _ilg.Load(_contextArg); _ilg.LoadMember(JsonFormatGeneratorStatics.UseSimpleDictionaryFormatReadProperty); _ilg.If(); if (!type.GetTypeInfo().IsValueType) { _ilg.If(_objectLocal, Cmp.EqualTo, null); _ilg.Call(null, XmlFormatGeneratorStatics.ThrowNullValueReturnedForGetOnlyCollectionExceptionMethod, type); _ilg.EndIf(); } ReadSimpleDictionary(collectionContract, itemType); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.CheckEndOfArrayMethod, _xmlReaderArg, size, _memberNamesArg, _emptyDictionaryStringArg); _ilg.Else(); } //check that items are actually going to be deserialized into the collection IsStartElement(_memberNamesArg, _emptyDictionaryStringArg); _ilg.If(); if (!type.GetTypeInfo().IsValueType) { _ilg.If(_objectLocal, Cmp.EqualTo, null); _ilg.Call(null, XmlFormatGeneratorStatics.ThrowNullValueReturnedForGetOnlyCollectionExceptionMethod, type); _ilg.EndIf(); } if (isArray) { _ilg.Load(_objectLocal); _ilg.Call(XmlFormatGeneratorStatics.GetArrayLengthMethod); _ilg.Stloc(size); } LocalBuilder i = _ilg.DeclareLocal(Globals.TypeOfInt, "i"); object forLoop = _ilg.For(i, 0, Int32.MaxValue); IsStartElement(_memberNamesArg, _emptyDictionaryStringArg); _ilg.If(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1); LocalBuilder value = ReadCollectionItem(collectionContract, itemType); if (isArray) { _ilg.If(size, Cmp.EqualTo, i); _ilg.Call(null, XmlFormatGeneratorStatics.ThrowArrayExceededSizeExceptionMethod, size, type); _ilg.Else(); _ilg.StoreArrayElement(_objectLocal, i, value); _ilg.EndIf(); } else StoreCollectionValue(_objectLocal, value, collectionContract); _ilg.Else(); IsEndElement(); _ilg.If(); _ilg.Break(forLoop); _ilg.Else(); HandleUnexpectedItemInCollection(i); _ilg.EndIf(); _ilg.EndIf(); _ilg.EndFor(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.CheckEndOfArrayMethod, _xmlReaderArg, size, _memberNamesArg, _emptyDictionaryStringArg); _ilg.EndIf(); if (canReadSimpleDictionary) { _ilg.EndIf(); } }
public void ReflectionReadGetOnlyCollection(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContextComplexJson context, XmlDictionaryString emptyDictionaryString, XmlDictionaryString itemName, CollectionDataContract collectionContract) { _reflectionReader.ReflectionReadGetOnlyCollection(xmlReader, context, itemName, emptyDictionaryString /*itemNamespace*/, collectionContract); }
void WriteCollection(CollectionDataContract collectionContract) { XmlDictionaryString itemName = context.CollectionItemName; if (collectionContract.Kind == CollectionKind.Array) { Type itemType = collectionContract.ItemType; int i; // This check does not exist in the original dynamic code, // but there is no other way to check type mismatch. // CollectionSerialization.ArrayContract() shows that it is required. if (objLocal.GetType ().GetElementType () != itemType) throw new InvalidCastException (string.Format ("Cannot cast array of {0} to array of {1}", objLocal.GetType ().GetElementType (), itemType)); context.IncrementArrayCount (writer, (Array) objLocal); if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, () => objLocal, itemName)) { WriteArrayAttribute (); var arr = (Array) objLocal; var idx = new int [1]; for (i = 0; i < arr.Length; i++) { if (!TryWritePrimitive(itemType, null, null, i, itemName, 0)) { WriteStartElement (itemName, 0); idx [0] = i; var mbrVal = arr.GetValue (idx); WriteValue (itemType, mbrVal); WriteEndElement (); } } } } else { // This check does not exist in the original dynamic code, // but there is no other way to check type mismatch. // CollectionSerialization.ArrayContract() shows that it is required. if (!collectionContract.UnderlyingType.IsAssignableFrom (objLocal.GetType ())) throw new InvalidCastException (string.Format ("Cannot cast {0} to {1}", objLocal.GetType (), collectionContract.UnderlyingType)); MethodInfo incrementCollectionCountMethod = null; switch (collectionContract.Kind) { case CollectionKind.Collection: case CollectionKind.List: case CollectionKind.Dictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod; break; case CollectionKind.GenericCollection: case CollectionKind.GenericList: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType); break; case CollectionKind.GenericDictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments())); break; } if (incrementCollectionCountMethod != null) incrementCollectionCountMethod.Invoke (context, new object [] {writer, objLocal}); bool isDictionary = false, isGenericDictionary = false; Type enumeratorType = null; Type [] keyValueTypes = null; if (collectionContract.Kind == CollectionKind.GenericDictionary) { isGenericDictionary = true; keyValueTypes = collectionContract.ItemType.GetGenericArguments (); enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType (keyValueTypes); } else if (collectionContract.Kind == CollectionKind.Dictionary) { isDictionary = true; keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject }; enumeratorType = Globals.TypeOfDictionaryEnumerator; } else { enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType; } MethodInfo moveNextMethod = enumeratorType.GetMethod (Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); MethodInfo getCurrentMethod = enumeratorType.GetMethod (Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); if (moveNextMethod == null || getCurrentMethod == null) { if (enumeratorType.IsInterface) { if (moveNextMethod == null) moveNextMethod = JsonFormatGeneratorStatics.MoveNextMethod; if (getCurrentMethod == null) getCurrentMethod = JsonFormatGeneratorStatics.GetCurrentMethod; } else { Type ienumeratorInterface = Globals.TypeOfIEnumerator; CollectionKind kind = collectionContract.Kind; if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable) { Type[] interfaceTypes = enumeratorType.GetInterfaces(); foreach (Type interfaceType in interfaceTypes) { if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric && interfaceType.GetGenericArguments()[0] == collectionContract.ItemType) { ienumeratorInterface = interfaceType; break; } } } if (moveNextMethod == null) moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface); if (getCurrentMethod == null) getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface); } } Type elementType = getCurrentMethod.ReturnType; object currentValue = null; // of elementType var enumerator = (IEnumerator) collectionContract.GetEnumeratorMethod.Invoke (objLocal, new object [0]); if (isDictionary) { ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor (Globals.ScanAllMembers, null, new Type[] { Globals.TypeOfIDictionaryEnumerator }, null); enumerator = (IEnumerator) dictEnumCtor.Invoke (new object [] {enumerator}); } else if (isGenericDictionary) { Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes)); ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null); enumerator = (IEnumerator) Activator.CreateInstance (enumeratorType, new object [] {enumerator}); } bool canWriteSimpleDictionary = isDictionary || isGenericDictionary; bool writeSimpleDictionary = canWriteSimpleDictionary && context.UseSimpleDictionaryFormat; PropertyInfo genericDictionaryKeyProperty = null, genericDictionaryValueProperty = null; if (canWriteSimpleDictionary) { Type genericDictionaryKeyValueType = Globals.TypeOfKeyValue.MakeGenericType (keyValueTypes); genericDictionaryKeyProperty = genericDictionaryKeyValueType.GetProperty (JsonGlobals.KeyString); genericDictionaryValueProperty = genericDictionaryKeyValueType.GetProperty (JsonGlobals.ValueString); } if (writeSimpleDictionary) { WriteObjectAttribute (); object key, value; var empty_args = new object [0]; while ((bool) moveNextMethod.Invoke (enumerator, empty_args)) { currentValue = getCurrentMethod.Invoke (enumerator, empty_args); key = CodeInterpreter.GetMember (genericDictionaryKeyProperty, currentValue); value = CodeInterpreter.GetMember (genericDictionaryValueProperty, currentValue); WriteStartElement (key, 0 /*nameIndex*/); WriteValue (genericDictionaryValueProperty.PropertyType, value); WriteEndElement (); } } else { WriteArrayAttribute (); var emptyArray = new object [0]; while (enumerator != null && enumerator.MoveNext ()) { currentValue = getCurrentMethod.Invoke (enumerator, emptyArray); if (incrementCollectionCountMethod == null) XmlFormatGeneratorStatics.IncrementItemCountMethod.Invoke (context, new object [] {1}); if (!TryWritePrimitive (elementType, () => currentValue, null, null, itemName, 0)) { WriteStartElement (itemName, 0); if (isGenericDictionary || isDictionary) { var jc = JsonDataContract.GetJsonDataContract (XmlObjectSerializerWriteContextComplexJson.GetRevisedItemContract ( collectionDataContract.ItemContract)); // FIXME: this TypeHandle might be wrong; there is no easy way to get Type for currentValue though. DataContractJsonSerializer.WriteJsonValue (jc, writer, currentValue, context, currentValue.GetType ().TypeHandle); } else WriteValue (elementType, currentValue); WriteEndElement (); } } } } }
protected override string GetCollectionContractItemName(CollectionDataContract collectionContract) { return(JsonGlobals.itemString); }
void StoreKeyValuePair(LocalBuilder collection, CollectionDataContract collectionContract, LocalBuilder pairKey, LocalBuilder pairValue) { ilg.Call(collection, collectionContract.AddMethod, pairKey, pairValue); if (collectionContract.AddMethod.ReturnType != Globals.TypeOfVoid) ilg.Pop(); }
protected override string GetCollectionContractNamespace(CollectionDataContract collectionContract) { return(string.Empty); }
public XmlFormatGetOnlyCollectionReaderDelegate GenerateGetOnlyCollectionReader(CollectionDataContract collectionContract) { ilg = GenerateCollectionReaderHelper(collectionContract, true /*isGetOnlyCollection*/); ReadGetOnlyCollection(collectionContract); return (XmlFormatGetOnlyCollectionReaderDelegate)ilg.EndMethod(); }
protected override object ReflectionReadDictionaryItem(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, CollectionDataContract collectionContract) { var jsonContext = context as XmlObjectSerializerReadContextComplexJson; Debug.Assert(jsonContext != null); Debug.Assert(collectionContract.Kind == CollectionKind.Dictionary || collectionContract.Kind == CollectionKind.GenericDictionary); context.ReadAttributes(xmlReader); var itemContract = XmlObjectSerializerWriteContextComplexJson.GetRevisedItemContract(collectionContract.ItemContract); return(DataContractJsonSerializer.ReadJsonValue(itemContract, xmlReader, jsonContext)); }
LocalBuilder ReadCollectionItem(CollectionDataContract collectionContract, Type itemType, string itemName, string itemNs) { if (collectionContract.Kind == CollectionKind.Dictionary || collectionContract.Kind == CollectionKind.GenericDictionary) { ilg.Call(contextArg, XmlFormatGeneratorStatics.ResetAttributesMethod); LocalBuilder value = ilg.DeclareLocal(itemType, "valueRead"); ilg.Load(collectionContractArg); ilg.Call(XmlFormatGeneratorStatics.GetItemContractMethod); ilg.Load(xmlReaderArg); ilg.Load(contextArg); ilg.Call(XmlFormatGeneratorStatics.ReadXmlValueMethod); ilg.ConvertValue(Globals.TypeOfObject, itemType); ilg.Stloc(value); return value; } else { return ReadValue(itemType, itemName, itemNs); } }
private object ReadCollectionItems(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString collectionItemName, XmlDictionaryString collectionItemNamespace, CollectionDataContract collectionContract, object resultCollection, bool isReadOnlyCollection) { string itemName = GetCollectionContractItemName(collectionContract); string itemNs = GetCollectionContractNamespace(collectionContract); Type itemType = collectionContract.ItemType; CollectionReadItemDelegate collectionReadItemDelegate = GetCollectionReadItemDelegate(collectionContract); MethodInfo getCollectionSetItemDelegateMethod = s_getCollectionSetItemDelegateMethod.MakeGenericMethod(itemType); CollectionSetItemDelegate collectionSetItemDelegate = (CollectionSetItemDelegate)getCollectionSetItemDelegateMethod.Invoke(this, new object[] { collectionContract, resultCollection, isReadOnlyCollection }); int index = 0; while (true) { if (xmlReader.IsStartElement(collectionItemName, collectionItemNamespace)) { object collectionItem = collectionReadItemDelegate(xmlReader, context, collectionContract, itemType, itemName, itemNs); resultCollection = collectionSetItemDelegate(resultCollection, collectionItem, index); index++; } else { if (xmlReader.NodeType == XmlNodeType.EndElement) { break; } if (!xmlReader.IsStartElement()) { throw XmlObjectSerializerReadContext.CreateUnexpectedStateException(XmlNodeType.Element, xmlReader); } context.SkipUnknownElement(xmlReader); } } context.IncrementItemCount(index); if (!isReadOnlyCollection && IsArrayLikeCollection(collectionContract)) { MethodInfo trimArraySizeMethod = XmlFormatGeneratorStatics.TrimArraySizeMethod.MakeGenericMethod(itemType); resultCollection = trimArraySizeMethod.Invoke(null, new object[] { resultCollection, index }); } return(resultCollection); }
internal JsonFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract) { ilg = new CodeGenerator(); bool memberAccessFlag = collectionContract.RequiresMemberAccessForWrite(null); try { BeginMethod(ilg, "Write" + collectionContract.StableName.Name + "ToJson", typeof(JsonFormatCollectionWriterDelegate), memberAccessFlag); } catch (SecurityException securityException) { if (memberAccessFlag && securityException.PermissionType.Equals(typeof(ReflectionPermission))) { collectionContract.RequiresMemberAccessForWrite(securityException); } else { throw; } } InitArgs(collectionContract.UnderlyingType); DemandMemberAccessPermission(memberAccessFlag); if (collectionContract.IsReadOnlyContract) { ThrowIfCannotSerializeReadOnlyTypes(collectionContract); } WriteCollection(collectionContract); return (JsonFormatCollectionWriterDelegate)ilg.EndMethod(); }
protected abstract object ReflectionReadDictionaryItem(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, CollectionDataContract collectionContract);
void WriteCollection(CollectionDataContract collectionContract) { XmlDictionaryString itemNamespace = dataContract.Namespace; XmlDictionaryString itemName = collectionDataContract.CollectionItemName; if (collectionContract.ChildElementNamespace != null) { writer.WriteNamespaceDecl(collectionDataContract.ChildElementNamespace); } if (collectionContract.Kind == CollectionKind.Array) { Type itemType = collectionContract.ItemType; int i; // This check does not exist in the original dynamic code, // but there is no other way to check type mismatch. // CollectionSerialization.ArrayContract() shows that it is required. if (objLocal.GetType().GetElementType() != itemType) { throw new InvalidCastException(string.Format("Cannot cast array of {0} to array of {1}", objLocal.GetType().GetElementType(), itemType)); } ctx.IncrementArrayCount(writer, (Array)objLocal); if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, () => objLocal, itemName, itemNamespace)) { var arr = (Array)objLocal; var idx = new int [1]; for (i = 0; i < arr.Length; i++) { if (!TryWritePrimitive(itemType, null, null, i, itemNamespace, itemName, 0)) { WriteStartElement(itemType, collectionContract.Namespace, itemNamespace, itemName, 0); idx [0] = i; var mbrVal = arr.GetValue(idx); WriteValue(itemType, mbrVal, false); WriteEndElement(); } } } } else { // This check does not exist in the original dynamic code, // but there is no other way to check type mismatch. // CollectionSerialization.ArrayContract() shows that it is required. if (!collectionContract.UnderlyingType.IsAssignableFrom(objLocal.GetType())) { throw new InvalidCastException(string.Format("Cannot cast {0} to {1}", objLocal.GetType(), collectionContract.UnderlyingType)); } MethodInfo incrementCollectionCountMethod = null; switch (collectionContract.Kind) { case CollectionKind.Collection: case CollectionKind.List: case CollectionKind.Dictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod; break; case CollectionKind.GenericCollection: case CollectionKind.GenericList: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType); break; case CollectionKind.GenericDictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments())); break; } if (incrementCollectionCountMethod != null) { incrementCollectionCountMethod.Invoke(ctx, new object [] { writer, objLocal }); } bool isDictionary = false, isGenericDictionary = false; Type enumeratorType = null; Type [] keyValueTypes = null; if (collectionContract.Kind == CollectionKind.GenericDictionary) { isGenericDictionary = true; keyValueTypes = collectionContract.ItemType.GetGenericArguments(); enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType(keyValueTypes); } else if (collectionContract.Kind == CollectionKind.Dictionary) { isDictionary = true; keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject }; enumeratorType = Globals.TypeOfDictionaryEnumerator; } else { enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType; } MethodInfo moveNextMethod = enumeratorType.GetMethod(Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); MethodInfo getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, null, Globals.EmptyTypeArray, null); if (moveNextMethod == null || getCurrentMethod == null) { if (enumeratorType.IsInterface) { if (moveNextMethod == null) { moveNextMethod = XmlFormatGeneratorStatics.MoveNextMethod; } if (getCurrentMethod == null) { getCurrentMethod = XmlFormatGeneratorStatics.GetCurrentMethod; } } else { Type ienumeratorInterface = Globals.TypeOfIEnumerator; CollectionKind kind = collectionContract.Kind; if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable) { Type[] interfaceTypes = enumeratorType.GetInterfaces(); foreach (Type interfaceType in interfaceTypes) { if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric && interfaceType.GetGenericArguments()[0] == collectionContract.ItemType) { ienumeratorInterface = interfaceType; break; } } } if (moveNextMethod == null) { moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface); } if (getCurrentMethod == null) { getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface); } } } Type elementType = getCurrentMethod.ReturnType; object currentValue = null; // of elementType var enumerator = (IEnumerator)collectionContract.GetEnumeratorMethod.Invoke(objLocal, new object [0]); if (isDictionary) { enumerator = new CollectionDataContract.DictionaryEnumerator((IDictionaryEnumerator)enumerator); } else if (isGenericDictionary) { Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes)); ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, null, new Type[] { ctorParam }, null); enumerator = (IEnumerator)Activator.CreateInstance(enumeratorType, new object [] { enumerator }); } var emptyArray = new object [0]; while (enumerator != null && enumerator.MoveNext()) { currentValue = getCurrentMethod.Invoke(enumerator, emptyArray); if (incrementCollectionCountMethod == null) { XmlFormatGeneratorStatics.IncrementItemCountMethod.Invoke(ctx, new object [] { 1 }); } if (!TryWritePrimitive(elementType, () => currentValue, null, null, itemNamespace, itemName, 0)) { WriteStartElement(elementType, collectionContract.Namespace, itemNamespace, itemName, 0); if (isGenericDictionary || isDictionary) { collectionDataContract.ItemContract.WriteXmlValue(writer, currentValue, ctx); } else { WriteValue(elementType, currentValue, false); } WriteEndElement(); } } } }
protected abstract string GetCollectionContractItemName(CollectionDataContract collectionContract);
private CodeGenerator GenerateCollectionReaderHelper(CollectionDataContract collectionContract, bool isGetOnlyCollection) { _ilg = new CodeGenerator(); bool memberAccessFlag = collectionContract.RequiresMemberAccessForRead(null); try { if (isGetOnlyCollection) { BeginMethod(_ilg, "Read" + DataContract.SanitizeTypeName(collectionContract.StableName.Name) + "FromJson" + "IsGetOnly", typeof(JsonFormatGetOnlyCollectionReaderDelegate), memberAccessFlag); } else { BeginMethod(_ilg, "Read" + DataContract.SanitizeTypeName(collectionContract.StableName.Name) + "FromJson", typeof(JsonFormatCollectionReaderDelegate), memberAccessFlag); } } catch (SecurityException securityException) { if (memberAccessFlag) { collectionContract.RequiresMemberAccessForRead(securityException); } else { throw; } } InitArgs(); _collectionContractArg = _ilg.GetArg(4); return _ilg; }
protected abstract string GetCollectionContractNamespace(CollectionDataContract collectionContract);
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(); } }
protected virtual bool ReflectionReadSpecialCollection(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, CollectionDataContract collectionContract, object resultCollection) { return(false); }
private LocalBuilder ReadCollectionItem(CollectionDataContract collectionContract, Type itemType) { if (collectionContract.Kind == CollectionKind.Dictionary || collectionContract.Kind == CollectionKind.GenericDictionary) { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.ResetAttributesMethod); LocalBuilder value = _ilg.DeclareLocal(itemType, "valueRead"); _ilg.Load(_collectionContractArg); _ilg.Call(JsonFormatGeneratorStatics.GetItemContractMethod); _ilg.Call(JsonFormatGeneratorStatics.GetRevisedItemContractMethod); _ilg.Load(_xmlReaderArg); _ilg.Load(_contextArg); _ilg.Call(JsonFormatGeneratorStatics.ReadJsonValueMethod); _ilg.ConvertValue(Globals.TypeOfObject, itemType); _ilg.Stloc(value); return value; } else { return ReadValue(itemType, JsonGlobals.itemString); } }
private object ReflectionInternalDeserialize(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, CollectionDataContract collectionContract, Type type, string name, string ns) { return(context.InternalDeserialize(xmlReader, DataContract.GetId(type.TypeHandle), type.TypeHandle, name, ns)); }
internal JsonFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract) { return (XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContextComplexJson context, CollectionDataContract dataContract) => new JsonFormatWriterInterpreter (collectionContract).WriteCollectionToJson (xmlWriter, obj, context, dataContract); }
private bool IsArrayLikeCollection(CollectionDataContract collectionContract) { return(collectionContract.Kind == CollectionKind.Array || IsArrayLikeInterface(collectionContract)); }
public static IEnumerable ConvertGenericListToArray(DataContractJsonSerializer serializer, IEnumerable value, CollectionDataContract dataContract, XmlObjectSerializerWriteContextComplexJson context, bool writeServerType) { Type listArgumentType = dataContract.ItemType; if (listArgumentType.GetTypeInfo().IsGenericType) { listArgumentType = listArgumentType.GetGenericArguments()[0]; } List <object> serializedList = new List <object>(); MethodInfo getEnumeratorMethod = dataContract.GetEnumeratorMethod; IEnumerator enumerator = (getEnumeratorMethod == null) ? value.GetEnumerator() : (IEnumerator)getEnumeratorMethod.Invoke(value, Globals.EmptyTypeArray); while (enumerator.MoveNext()) { if (enumerator.Current == null || enumerator.Current.GetType().GetTypeInfo().IsPrimitive) { serializedList.Add(enumerator.Current); } else { Type currentItemType = enumerator.Current.GetType(); DataContract currentItemDataContract = DataContract.GetDataContract(currentItemType); bool emitTypeInformation = EmitTypeInformation(dataContract.ItemContract, currentItemType); if (writeServerType || emitTypeInformation) { context.CheckIfTypeNeedsVerifcation(dataContract.ItemContract, currentItemDataContract); } context.PushKnownTypes(dataContract); serializedList.Add(serializer.ConvertDataContractToObject(enumerator.Current, currentItemDataContract, context, (writeServerType || emitTypeInformation), dataContract.ItemType.TypeHandle)); context.PopKnownTypes(dataContract); } } return(serializedList); }
private CollectionSetItemDelegate GetCollectionSetItemDelegate <T>(CollectionDataContract collectionContract, object resultCollectionObject, bool isReadOnlyCollection) { if (isReadOnlyCollection && collectionContract.Kind == CollectionKind.Array) { int arraySize = ((Array)resultCollectionObject).Length; return((resultCollection, collectionItem, index) => { if (index == arraySize) { XmlObjectSerializerReadContext.ThrowArrayExceededSizeException(arraySize, collectionContract.UnderlyingType); } ((T[])resultCollection)[index] = (T)collectionItem; return resultCollection; }); } else if (!isReadOnlyCollection && IsArrayLikeCollection(collectionContract)) { return((resultCollection, collectionItem, index) => { resultCollection = XmlObjectSerializerReadContext.EnsureArraySize((T[])resultCollection, index); ((T[])resultCollection)[index] = (T)collectionItem; return resultCollection; }); } else if (collectionContract.Kind == CollectionKind.GenericDictionary || collectionContract.Kind == CollectionKind.Dictionary) { Type keyType = collectionContract.ItemType.GenericTypeArguments[0]; Type valueType = collectionContract.ItemType.GenericTypeArguments[1]; Func <object, object> objectToKeyValuePairGetKey = s_objectToKeyValuePairGetKey.MakeGenericMethod(keyType, valueType).CreateDelegate <Func <object, object> >(); Func <object, object> objectToKeyValuePairGetValue = s_objectToKeyValuePairGetValue.MakeGenericMethod(keyType, valueType).CreateDelegate <Func <object, object> >(); if (collectionContract.Kind == CollectionKind.GenericDictionary) { return((resultCollection, collectionItem, index) => { object key = objectToKeyValuePairGetKey(collectionItem); object value = objectToKeyValuePairGetValue(collectionItem); collectionContract.AddMethod.Invoke(resultCollection, new object[] { key, value }); return resultCollection; }); } else { return((resultCollection, collectionItem, index) => { object key = objectToKeyValuePairGetKey(collectionItem); object value = objectToKeyValuePairGetValue(collectionItem); IDictionary dict = (IDictionary)resultCollection; dict.Add(key, value); return resultCollection; }); } } else { Type collectionType = resultCollectionObject.GetType(); Type genericCollectionType = typeof(ICollection <T>); Type typeIList = Globals.TypeOfIList; if (genericCollectionType.IsAssignableFrom(collectionType)) { return((resultCollection, collectionItem, index) => { ((ICollection <T>)resultCollection).Add((T)collectionItem); return resultCollection; }); } else if (typeIList.IsAssignableFrom(collectionType)) { return((resultCollection, collectionItem, index) => { ((IList)resultCollection).Add(collectionItem); return resultCollection; }); } else { MethodInfo addMethod = collectionContract.AddMethod; if (addMethod == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException(SR.Format(SR.CollectionMustHaveAddMethod, DataContract.GetClrTypeFullName(collectionContract.UnderlyingType)))); } return((resultCollection, collectionItem, index) => { addMethod.Invoke(resultCollection, new object[] { collectionItem }); return resultCollection; }); } } }
public void ReflectionWriteCollection(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContextComplexJson context, CollectionDataContract collectionContract) { JsonWriterDelegator jsonWriter = xmlWriter as JsonWriterDelegator; if (jsonWriter == null) { throw new ArgumentException(nameof(xmlWriter)); } XmlDictionaryString itemName = context.CollectionItemName; if (collectionContract.Kind == CollectionKind.Array) { context.IncrementArrayCount(jsonWriter, (Array)obj); Type itemType = collectionContract.ItemType; if (!ReflectionTryWritePrimitiveArray(jsonWriter, obj, collectionContract.UnderlyingType, itemType, itemName)) { ReflectionWriteArrayAttribute(jsonWriter); Array array = (Array)obj; PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(itemType); for (int i = 0; i < array.Length; ++i) { _reflectionClassWriter.ReflectionWriteStartElement(jsonWriter, itemName); _reflectionClassWriter.ReflectionWriteValue(jsonWriter, context, itemType, array.GetValue(i), false, primitiveContract); _reflectionClassWriter.ReflectionWriteEndElement(jsonWriter); } } } else { collectionContract.IncrementCollectionCount(jsonWriter, obj, context); Type enumeratorReturnType; IEnumerator enumerator = collectionContract.GetEnumeratorForCollection(obj, out enumeratorReturnType); bool canWriteSimpleDictionary = collectionContract.Kind == CollectionKind.GenericDictionary || collectionContract.Kind == CollectionKind.Dictionary; bool useSimpleDictionaryFormat = context.UseSimpleDictionaryFormat; if (canWriteSimpleDictionary && useSimpleDictionaryFormat) { ReflectionWriteObjectAttribute(jsonWriter); while (enumerator.MoveNext()) { object current = enumerator.Current; object key = ((IKeyValue)current).Key; object value = ((IKeyValue)current).Value; _reflectionClassWriter.ReflectionWriteStartElement(jsonWriter, key.ToString()); _reflectionClassWriter.ReflectionWriteValue(jsonWriter, context, value.GetType(), value, false, primitiveContractForParamType: null); _reflectionClassWriter.ReflectionWriteEndElement(jsonWriter); } } else { ReflectionWriteArrayAttribute(jsonWriter); PrimitiveDataContract primitiveContractForType = PrimitiveDataContract.GetPrimitiveDataContract(enumeratorReturnType); if (primitiveContractForType != null && primitiveContractForType.UnderlyingType != Globals.TypeOfObject) { while (enumerator.MoveNext()) { object current = enumerator.Current; context.IncrementItemCount(1); primitiveContractForType.WriteXmlElement(jsonWriter, current, context, itemName, null /*namespace*/); } } else { bool isDictionary = collectionContract.Kind == CollectionKind.Dictionary || collectionContract.Kind == CollectionKind.GenericDictionary; while (enumerator.MoveNext()) { object current = enumerator.Current; context.IncrementItemCount(1); _reflectionClassWriter.ReflectionWriteStartElement(jsonWriter, itemName); if (isDictionary) { var itemContract = XmlObjectSerializerWriteContextComplexJson.GetRevisedItemContract(collectionContract.ItemContract); var jsonDataContract = JsonDataContract.GetJsonDataContract(itemContract); jsonDataContract.WriteJsonValue(jsonWriter, current, context, collectionContract.ItemType.TypeHandle); } else { _reflectionClassWriter.ReflectionWriteValue(jsonWriter, context, enumeratorReturnType, current, false, primitiveContractForParamType: null); } _reflectionClassWriter.ReflectionWriteEndElement(jsonWriter); } } } } }
public void ReflectionReadGetOnlyCollection(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString collectionItemName, XmlDictionaryString collectionItemNamespace, CollectionDataContract collectionContract) { object resultCollection = context.GetCollectionMember(); if (ReflectionReadSpecialCollection(xmlReader, context, collectionContract, resultCollection)) { return; } if (xmlReader.IsStartElement(collectionItemName, collectionItemNamespace)) { if (resultCollection == null) { XmlObjectSerializerReadContext.ThrowNullValueReturnedForGetOnlyCollectionException(collectionContract.UnderlyingType); } bool isReadOnlyCollection = true; resultCollection = ReadCollectionItems(xmlReader, context, collectionItemName, collectionItemNamespace, collectionContract, resultCollection, isReadOnlyCollection); } }
public XmlFormatCollectionReaderDelegate GenerateCollectionReader(CollectionDataContract collectionContract) { ilg = GenerateCollectionReaderHelper(collectionContract, false /*isGetOnlyCollection*/); ReadCollection(collectionContract); ilg.Load(objectLocal); ilg.ConvertValue(objectLocal.LocalType, ilg.CurrentMethod.ReturnType); return (XmlFormatCollectionReaderDelegate)ilg.EndMethod(); }
public object ReflectionReadCollection(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString collectionItemName, XmlDictionaryString collectionItemNamespace, CollectionDataContract collectionContract) { return(ReflectionReadCollectionCore(xmlReader, context, collectionItemName, collectionItemNamespace, collectionContract)); }
CodeGenerator GenerateCollectionReaderHelper(CollectionDataContract collectionContract, bool isGetOnlyCollection) { ilg = new CodeGenerator(); bool memberAccessFlag = collectionContract.RequiresMemberAccessForRead(null); try { if (isGetOnlyCollection) { ilg.BeginMethod("Read" + collectionContract.StableName.Name + "FromXml" + "IsGetOnly", Globals.TypeOfXmlFormatGetOnlyCollectionReaderDelegate, memberAccessFlag); } else { ilg.BeginMethod("Read" + collectionContract.StableName.Name + "FromXml" + string.Empty, Globals.TypeOfXmlFormatCollectionReaderDelegate, memberAccessFlag); } } catch (SecurityException securityException) { if (memberAccessFlag && securityException.PermissionType.Equals(typeof(ReflectionPermission))) { collectionContract.RequiresMemberAccessForRead(securityException); } else { throw; } } InitArgs(); DemandMemberAccessPermission(memberAccessFlag); collectionContractArg = ilg.GetArg(4); return ilg; }
private object ReflectionReadCollectionCore(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context, XmlDictionaryString collectionItemName, XmlDictionaryString collectionItemNamespace, CollectionDataContract collectionContract) { bool isArray = (collectionContract.Kind == CollectionKind.Array); int arraySize = context.GetArraySize(); object resultArray = null; if (isArray && ReflectionTryReadPrimitiveArray(xmlReader, context, collectionItemName, collectionItemNamespace, collectionContract.UnderlyingType, collectionContract.ItemType, arraySize, out resultArray)) { return(resultArray); } object resultCollection = ReflectionCreateCollection(collectionContract); context.AddNewObject(resultCollection); context.IncrementItemCount(1); if (!ReflectionReadSpecialCollection(xmlReader, context, collectionContract, resultCollection)) { bool isReadOnlyCollection = false; resultCollection = ReadCollectionItems(xmlReader, context, collectionItemName, collectionItemNamespace, collectionContract, resultCollection, isReadOnlyCollection); } return(resultCollection); }
void ReadGetOnlyCollection(CollectionDataContract collectionContract) { Type type = collectionContract.UnderlyingType; Type itemType = collectionContract.ItemType; bool isArray = (collectionContract.Kind == CollectionKind.Array); string itemName = collectionContract.ItemName; string itemNs = collectionContract.StableName.Namespace; objectLocal = ilg.DeclareLocal(type, "objectDeserialized"); ilg.Load(contextArg); ilg.LoadMember(XmlFormatGeneratorStatics.GetCollectionMemberMethod); ilg.ConvertValue(Globals.TypeOfObject, type); ilg.Stloc(objectLocal); //check that items are actually going to be deserialized into the collection IsStartElement(memberNamesArg, memberNamespacesArg); ilg.If(); ilg.If(objectLocal, Cmp.EqualTo, null); ilg.Call(null, XmlFormatGeneratorStatics.ThrowNullValueReturnedForGetOnlyCollectionExceptionMethod, type); ilg.Else(); LocalBuilder size = ilg.DeclareLocal(Globals.TypeOfInt, "arraySize"); if (isArray) { ilg.Load(objectLocal); ilg.Call(XmlFormatGeneratorStatics.GetArrayLengthMethod); ilg.Stloc(size); } ilg.Call(contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, objectLocal); LocalBuilder i = ilg.DeclareLocal(Globals.TypeOfInt, "i"); object forLoop = ilg.For(i, 0, Int32.MaxValue); IsStartElement(memberNamesArg, memberNamespacesArg); ilg.If(); ilg.Call(contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1); LocalBuilder value = ReadCollectionItem(collectionContract, itemType, itemName, itemNs); if (isArray) { ilg.If(size, Cmp.EqualTo, i); ilg.Call(null, XmlFormatGeneratorStatics.ThrowArrayExceededSizeExceptionMethod, size, type); ilg.Else(); ilg.StoreArrayElement(objectLocal, i, value); ilg.EndIf(); } else StoreCollectionValue(objectLocal, value, collectionContract); ilg.Else(); IsEndElement(); ilg.If(); ilg.Break(forLoop); ilg.Else(); HandleUnexpectedItemInCollection(i); ilg.EndIf(); ilg.EndIf(); ilg.EndFor(); ilg.Call(contextArg, XmlFormatGeneratorStatics.CheckEndOfArrayMethod, xmlReaderArg, size, memberNamesArg, memberNamespacesArg); ilg.EndIf(); ilg.EndIf(); }
private static void FindRefHandleCollectionDataContractMembers(object data, DataContract dataContract, ref Dictionary <DataContract, List <RefData> > alreadyRefdValues, ref Dictionary <DataContract, List <RefData> > nonRefdValues) { CollectionDataContract collectionContract = dataContract as CollectionDataContract; if (!collectionContract.IsDictionary) { foreach (object obj in (IEnumerable)data) { if (obj != null) { FindAndAddRefd(obj, DataContract.GetDataContract(obj.GetType(), supportCollectionDataContract), ref alreadyRefdValues, ref nonRefdValues); } } } else { IDictionary dictionary = data as IDictionary; if (dictionary != null) { foreach (object key in dictionary.Keys) { if (key != null) { FindAndAddRefd(key, DataContract.GetDataContract(key.GetType(), supportCollectionDataContract), ref alreadyRefdValues, ref nonRefdValues); } } foreach (object value in dictionary.Values) { if (value != null) { FindAndAddRefd(value, DataContract.GetDataContract(value.GetType(), supportCollectionDataContract), ref alreadyRefdValues, ref nonRefdValues); } } } else { if (collectionContract.GetEnumeratorMethod != null) { object dictEnumObj = null; try { dictEnumObj = collectionContract.GetEnumeratorMethod.Invoke(data, new object[] { }); } catch (Exception) { } IDictionaryEnumerator dictEnum = dictEnumObj as IDictionaryEnumerator; if (dictEnum != null) { while (dictEnum.MoveNext()) { FindAndAddRefd(dictEnum.Key, DataContract.GetDataContract(dictEnum.Key.GetType(), supportCollectionDataContract), ref alreadyRefdValues, ref nonRefdValues); } dictEnum.Reset(); while (dictEnum.MoveNext()) { if (dictEnum.Value != null) { FindAndAddRefd(dictEnum.Value, DataContract.GetDataContract(dictEnum.Value.GetType(), supportCollectionDataContract), ref alreadyRefdValues, ref nonRefdValues); } } } } else { throw new Exception("TestDriver Exception: Dictionary CollectionDataCotnract Type Not Supported"); } } } }
//Deserialize '[...]' json string. The contents of the list can also be a dictionary i.e. [{...}]. The content type is detected //based on the type of CollectionDataContract.ItemContract. public static object ConvertICollectionToCollectionDataContract(DataContractJsonSerializer serializer, CollectionDataContract contract, object deserializedValue, XmlObjectSerializerReadContextComplexJson context) { Dictionary <string, object> valueAsDictionary = deserializedValue as Dictionary <string, object>; //Check to see if the dictionary (if it is a dictionary)is a regular Dictionary i.e { Key="key"; Value="value} and doesnt contain the __type string //for ex. the dictionary { __type="XXX"; Key="key"; Value="value} needs to be parsed as ClassDataContract if (valueAsDictionary != null && (!valueAsDictionary.ContainsKey(JsonGlobals.KeyString) || valueAsDictionary.ContainsKey(JsonGlobals.ServerTypeString))) { //If not then its a dictionary for either of these cases //1. Empty object - {} //2. Containes the __type information //3. Is a DateTimeOffsetDictionary return(ConvertDictionary(serializer, contract, valueAsDictionary, context)); } object returnValue = (contract.Constructor != null) ? contract.Constructor.Invoke(Array.Empty <Type>()) : null; bool isCollectionDataContractDictionary = contract.IsDictionary; MethodInfo addMethod = contract.AddMethod; bool convertToArray = contract.Kind == CollectionKind.Array; if (contract.UnderlyingType.GetTypeInfo().IsInterface || returnValue == null) { switch (contract.Kind) { case CollectionKind.Collection: case CollectionKind.GenericCollection: case CollectionKind.Enumerable: case CollectionKind.GenericEnumerable: case CollectionKind.List: case CollectionKind.GenericList: case CollectionKind.Array: if (contract.UnderlyingType.GetTypeInfo().IsValueType) { //Initialize struct returnValue = XmlFormatReaderGenerator.TryGetUninitializedObjectWithFormatterServices(contract.UnderlyingType); } else { returnValue = Activator.CreateInstance(Globals.TypeOfListGeneric.MakeGenericType(contract.ItemType)); convertToArray = true; } break; case CollectionKind.GenericDictionary: returnValue = Activator.CreateInstance(Globals.TypeOfDictionaryGeneric.MakeGenericType(contract.ItemType.GetGenericArguments())); break; case CollectionKind.Dictionary: returnValue = Activator.CreateInstance(Globals.TypeOfDictionaryGeneric.MakeGenericType(Globals.TypeOfObject, Globals.TypeOfObject)); break; } } if (addMethod == null) { //addMethod is null for IDictionary, IList and array types. Type[] paramArray = (contract.ItemType.GetTypeInfo().IsGenericType&& !convertToArray) ? contract.ItemType.GetGenericArguments() : new Type[] { contract.ItemType }; addMethod = returnValue.GetType().GetMethod(Globals.AddMethodName, paramArray); } IEnumerator enumerator = ((ICollection)deserializedValue).GetEnumerator(); object currentItem = null; object[] currentItemArray = null; while (enumerator.MoveNext()) { DataContract itemContract = contract.ItemContract; if (itemContract is ClassDataContract) { itemContract = XmlObjectSerializerWriteContextComplexJson.GetRevisedItemContract(itemContract); } currentItem = serializer.ConvertObjectToDataContract(itemContract, enumerator.Current, context); currentItemArray = new object[] { currentItem }; if (isCollectionDataContractDictionary) { Type currentItemType = currentItem.GetType(); MemberInfo keyMember = currentItemType.GetMember("Key")[0]; MemberInfo valueMember = currentItemType.GetMember("Value")[0]; currentItemArray = new object[] { DataContractToObjectConverter.GetMemberValue(currentItem, keyMember, currentItemType), DataContractToObjectConverter.GetMemberValue(currentItem, valueMember, currentItemType) }; } addMethod.Invoke(returnValue, currentItemArray); } return((convertToArray) ? ConvertToArray(contract.ItemType, (ICollection)returnValue) : returnValue); }
private void WriteCollection(CollectionDataContract collectionContract) { LocalBuilder itemNamespace = _ilg.DeclareLocal(typeof(XmlDictionaryString), "itemNamespace"); _ilg.Load(_dataContractArg); _ilg.LoadMember(XmlFormatGeneratorStatics.NamespaceProperty); _ilg.Store(itemNamespace); LocalBuilder itemName = _ilg.DeclareLocal(typeof(XmlDictionaryString), "itemName"); _ilg.Load(_dataContractArg); _ilg.LoadMember(XmlFormatGeneratorStatics.CollectionItemNameProperty); _ilg.Store(itemName); if (collectionContract.ChildElementNamespace != null) { _ilg.Load(_xmlWriterArg); _ilg.Load(_dataContractArg); _ilg.LoadMember(XmlFormatGeneratorStatics.ChildElementNamespaceProperty); _ilg.Call(XmlFormatGeneratorStatics.WriteNamespaceDeclMethod); } if (collectionContract.Kind == CollectionKind.Array) { Type itemType = collectionContract.ItemType; LocalBuilder i = _ilg.DeclareLocal(Globals.TypeOfInt, "i"); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementArrayCountMethod, _xmlWriterArg, _objectLocal); if (!TryWritePrimitiveArray(collectionContract.UnderlyingType, itemType, _objectLocal, itemName, itemNamespace)) { _ilg.For(i, 0, _objectLocal); if (!TryWritePrimitive(itemType, null /*value*/, null /*memberInfo*/, i /*arrayItemIndex*/, itemNamespace, itemName, 0 /*nameIndex*/)) { WriteStartElement(itemType, collectionContract.Namespace, itemNamespace, itemName, 0 /*nameIndex*/); _ilg.LoadArrayElement(_objectLocal, i); LocalBuilder memberValue = _ilg.DeclareLocal(itemType, "memberValue"); _ilg.Stloc(memberValue); WriteValue(memberValue, false /*writeXsiType*/); WriteEndElement(); } _ilg.EndFor(); } } else { MethodInfo incrementCollectionCountMethod = null; switch (collectionContract.Kind) { case CollectionKind.Collection: case CollectionKind.List: case CollectionKind.Dictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountMethod; break; case CollectionKind.GenericCollection: case CollectionKind.GenericList: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(collectionContract.ItemType); break; case CollectionKind.GenericDictionary: incrementCollectionCountMethod = XmlFormatGeneratorStatics.IncrementCollectionCountGenericMethod.MakeGenericMethod(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments())); break; } if (incrementCollectionCountMethod != null) { _ilg.Call(_contextArg, incrementCollectionCountMethod, _xmlWriterArg, _objectLocal); } bool isDictionary = false, isGenericDictionary = false; Type enumeratorType = null; Type[] keyValueTypes = null; if (collectionContract.Kind == CollectionKind.GenericDictionary) { isGenericDictionary = true; keyValueTypes = collectionContract.ItemType.GetGenericArguments(); enumeratorType = Globals.TypeOfGenericDictionaryEnumerator.MakeGenericType(keyValueTypes); } else if (collectionContract.Kind == CollectionKind.Dictionary) { isDictionary = true; keyValueTypes = new Type[] { Globals.TypeOfObject, Globals.TypeOfObject }; enumeratorType = Globals.TypeOfDictionaryEnumerator; } else { enumeratorType = collectionContract.GetEnumeratorMethod.ReturnType; } MethodInfo moveNextMethod = enumeratorType.GetMethod(Globals.MoveNextMethodName, BindingFlags.Instance | BindingFlags.Public, Globals.EmptyTypeArray); MethodInfo getCurrentMethod = enumeratorType.GetMethod(Globals.GetCurrentMethodName, BindingFlags.Instance | BindingFlags.Public, Globals.EmptyTypeArray); if (moveNextMethod == null || getCurrentMethod == null) { if (enumeratorType.GetTypeInfo().IsInterface) { if (moveNextMethod == null) { moveNextMethod = XmlFormatGeneratorStatics.MoveNextMethod; } if (getCurrentMethod == null) { getCurrentMethod = XmlFormatGeneratorStatics.GetCurrentMethod; } } else { Type ienumeratorInterface = Globals.TypeOfIEnumerator; CollectionKind kind = collectionContract.Kind; if (kind == CollectionKind.GenericDictionary || kind == CollectionKind.GenericCollection || kind == CollectionKind.GenericEnumerable) { Type[] interfaceTypes = enumeratorType.GetInterfaces(); foreach (Type interfaceType in interfaceTypes) { if (interfaceType.GetTypeInfo().IsGenericType && interfaceType.GetGenericTypeDefinition() == Globals.TypeOfIEnumeratorGeneric && interfaceType.GetGenericArguments()[0] == collectionContract.ItemType) { ienumeratorInterface = interfaceType; break; } } } if (moveNextMethod == null) { moveNextMethod = CollectionDataContract.GetTargetMethodWithName(Globals.MoveNextMethodName, enumeratorType, ienumeratorInterface); } if (getCurrentMethod == null) { getCurrentMethod = CollectionDataContract.GetTargetMethodWithName(Globals.GetCurrentMethodName, enumeratorType, ienumeratorInterface); } } } Type elementType = getCurrentMethod.ReturnType; LocalBuilder currentValue = _ilg.DeclareLocal(elementType, "currentValue"); LocalBuilder enumerator = _ilg.DeclareLocal(enumeratorType, "enumerator"); _ilg.Call(_objectLocal, collectionContract.GetEnumeratorMethod); if (isDictionary) { _ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, Globals.TypeOfIDictionaryEnumerator); _ilg.New(XmlFormatGeneratorStatics.DictionaryEnumeratorCtor); } else if (isGenericDictionary) { Type ctorParam = Globals.TypeOfIEnumeratorGeneric.MakeGenericType(Globals.TypeOfKeyValuePair.MakeGenericType(keyValueTypes)); ConstructorInfo dictEnumCtor = enumeratorType.GetConstructor(Globals.ScanAllMembers, new Type[] { ctorParam }); _ilg.ConvertValue(collectionContract.GetEnumeratorMethod.ReturnType, ctorParam); _ilg.New(dictEnumCtor); } _ilg.Stloc(enumerator); _ilg.ForEach(currentValue, elementType, enumeratorType, enumerator, getCurrentMethod); if (incrementCollectionCountMethod == null) { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.IncrementItemCountMethod, 1); } if (!TryWritePrimitive(elementType, currentValue, null /*memberInfo*/, null /*arrayItemIndex*/, itemNamespace, itemName, 0 /*nameIndex*/)) { WriteStartElement(elementType, collectionContract.Namespace, itemNamespace, itemName, 0 /*nameIndex*/); if (isGenericDictionary || isDictionary) { _ilg.Call(_dataContractArg, XmlFormatGeneratorStatics.GetItemContractMethod); _ilg.Load(_xmlWriterArg); _ilg.Load(currentValue); _ilg.ConvertValue(currentValue.LocalType, Globals.TypeOfObject); _ilg.Load(_contextArg); _ilg.Call(XmlFormatGeneratorStatics.WriteXmlValueMethod); } else { WriteValue(currentValue, false /*writeXsiType*/); } WriteEndElement(); } _ilg.EndForEach(moveNextMethod); } }
internal JsonFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract) { return _helper.GenerateCollectionWriter(collectionContract); }
public static List <object> ConvertGenericDictionaryToArray(DataContractJsonSerializer serializer, IEnumerable value, CollectionDataContract dataContract, XmlObjectSerializerWriteContextComplexJson context, bool writeServerType) { List <object> keyValuePair = new List <object>(); Dictionary <string, object> currentEntry; Type[] declaredTypes = dataContract.ItemType.GetGenericArguments(); MethodInfo getEnumeratorMethod = dataContract.GetEnumeratorMethod; IDictionaryEnumerator enumerator = (IDictionaryEnumerator)((getEnumeratorMethod == null) ? value.GetEnumerator() : (IDictionaryEnumerator)getEnumeratorMethod.Invoke(value, Globals.EmptyTypeArray)); while (enumerator.MoveNext()) { DictionaryEntry current = enumerator.Entry; DataContract currentDataContract = DataContract.GetDataContract(enumerator.Current.GetType()); currentEntry = new Dictionary <string, object>(); if (writeServerType) { AddTypeInformation(currentEntry, currentDataContract); } context.PushKnownTypes(dataContract); AddDictionaryEntryData(serializer, currentEntry, writeServerType ? JsonGlobals.KeyString.ToLowerInvariant() : JsonGlobals.KeyString, declaredTypes[0], current.Key, context); AddDictionaryEntryData(serializer, currentEntry, writeServerType ? JsonGlobals.ValueString.ToLowerInvariant() : JsonGlobals.ValueString, declaredTypes[1], current.Value, context); keyValuePair.Add(currentEntry); context.PopKnownTypes(dataContract); } return(keyValuePair); }
void ThrowIfCannotSerializeReadOnlyTypes(CollectionDataContract classContract) { ThrowIfCannotSerializeReadOnlyTypes(XmlFormatGeneratorStatics.CollectionSerializationExceptionMessageProperty); }
public XmlFormatCollectionReaderDelegate GenerateCollectionReader(CollectionDataContract collectionContract) { return _helper.GenerateCollectionReader(collectionContract); }
private void StoreCollectionValue(LocalBuilder collection, LocalBuilder value, CollectionDataContract collectionContract) { if (collectionContract.Kind == CollectionKind.GenericDictionary || collectionContract.Kind == CollectionKind.Dictionary) { ClassDataContract keyValuePairContract = DataContract.GetDataContract(value.LocalType) as ClassDataContract; if (keyValuePairContract == null) { DiagnosticUtility.DebugAssert("Failed to create contract for KeyValuePair type"); } DataMember keyMember = keyValuePairContract.Members[0]; DataMember valueMember = keyValuePairContract.Members[1]; LocalBuilder pairKey = _ilg.DeclareLocal(keyMember.MemberType, keyMember.Name); LocalBuilder pairValue = _ilg.DeclareLocal(valueMember.MemberType, valueMember.Name); _ilg.LoadAddress(value); _ilg.LoadMember(keyMember.MemberInfo); _ilg.Stloc(pairKey); _ilg.LoadAddress(value); _ilg.LoadMember(valueMember.MemberInfo); _ilg.Stloc(pairValue); _ilg.Call(collection, collectionContract.AddMethod, pairKey, pairValue); if (collectionContract.AddMethod.ReturnType != Globals.TypeOfVoid) { _ilg.Pop(); } } else { _ilg.Call(collection, collectionContract.AddMethod, value); if (collectionContract.AddMethod.ReturnType != Globals.TypeOfVoid) { _ilg.Pop(); } } }
internal XmlFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionDataContract collectionContract) { return(_helper.GenerateCollectionWriter(collectionContract)); }