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); IEnumerator enumerator = collectionContract.GetEnumeratorForCollection(obj); bool canWriteSimpleDictionary = collectionContract.Kind == CollectionKind.GenericDictionary || collectionContract.Kind == CollectionKind.Dictionary; bool useSimpleDictionaryFormat = context.UseSimpleDictionaryFormat; if (canWriteSimpleDictionary && useSimpleDictionaryFormat) { ReflectionWriteObjectAttribute(jsonWriter); Type[] itemTypeGenericArguments = collectionContract.ItemType.GetGenericArguments(); Type? dictionaryValueType = itemTypeGenericArguments.Length == 2 ? itemTypeGenericArguments[1] : null; 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, dictionaryValueType ?? value.GetType(), value, false, primitiveContractForParamType: null); _reflectionClassWriter.ReflectionWriteEndElement(jsonWriter); } } else { ReflectionWriteArrayAttribute(jsonWriter); PrimitiveDataContract?primitiveContractForType = PrimitiveDataContract.GetPrimitiveDataContract(collectionContract.UnderlyingType); 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 { Type elementType = collectionContract.GetCollectionElementType(); bool isDictionary = collectionContract.Kind == CollectionKind.Dictionary || collectionContract.Kind == CollectionKind.GenericDictionary; DataContract? itemContract = null; JsonDataContract?jsonDataContract = null; if (isDictionary) { itemContract = XmlObjectSerializerWriteContextComplexJson.GetRevisedItemContract(collectionContract.ItemContract); jsonDataContract = JsonDataContract.GetJsonDataContract(itemContract); } while (enumerator.MoveNext()) { object current = enumerator.Current; context.IncrementItemCount(1); _reflectionClassWriter.ReflectionWriteStartElement(jsonWriter, itemName); if (isDictionary) { jsonDataContract !.WriteJsonValue(jsonWriter, current, context, collectionContract.ItemType.TypeHandle); } else { _reflectionClassWriter.ReflectionWriteValue(jsonWriter, context, elementType, current, false, primitiveContractForParamType: null); } _reflectionClassWriter.ReflectionWriteEndElement(jsonWriter); } } } } }
private void WriteValue(LocalBuilder memberValue) { Type memberType = memberValue.LocalType; bool isNullableOfT = (memberType.IsGenericType && memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable); if (memberType.IsValueType && !isNullableOfT) { PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType); if (primitiveContract != null) { _ilg.Call(_xmlWriterArg, primitiveContract.XmlFormatContentWriterMethod, memberValue); } else { InternalSerialize(XmlFormatGeneratorStatics.InternalSerializeMethod, memberValue, memberType, false /* writeXsiType */); } } else { if (isNullableOfT) { memberValue = UnwrapNullableObject(memberValue); //Leaves !HasValue on stack memberType = memberValue.LocalType; } else { _ilg.Load(memberValue); _ilg.Load(null); _ilg.Ceq(); } _ilg.If(); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.WriteNullMethod, _xmlWriterArg, memberType, DataContract.IsTypeSerializable(memberType)); _ilg.Else(); PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType); if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) { if (isNullableOfT) { _ilg.Call(_xmlWriterArg, primitiveContract.XmlFormatContentWriterMethod, memberValue); } else { _ilg.Call(_contextArg, primitiveContract.XmlFormatContentWriterMethod, _xmlWriterArg, memberValue); } } else { if (memberType == Globals.TypeOfObject || //boxed Nullable<T> memberType == Globals.TypeOfValueType || ((IList)Globals.TypeOfNullable.GetInterfaces()).Contains(memberType)) { _ilg.Load(memberValue); _ilg.ConvertValue(memberValue.LocalType, Globals.TypeOfObject); memberValue = _ilg.DeclareLocal(Globals.TypeOfObject, "unwrappedMemberValue"); memberType = memberValue.LocalType; _ilg.Stloc(memberValue); _ilg.If(memberValue, Cmp.EqualTo, null); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.WriteNullMethod, _xmlWriterArg, memberType, DataContract.IsTypeSerializable(memberType)); _ilg.Else(); } InternalSerialize((isNullableOfT ? XmlFormatGeneratorStatics.InternalSerializeMethod : XmlFormatGeneratorStatics.InternalSerializeReferenceMethod), memberValue, memberType, false /* writeXsiType */); if (memberType == Globals.TypeOfObject) //boxed Nullable<T> { _ilg.EndIf(); } } _ilg.EndIf(); } }
private LocalBuilder ReadValue(Type type, string name) { LocalBuilder value = _ilg.DeclareLocal(type, "valueRead"); LocalBuilder nullableValue = null; int nullables = 0; while (type.GetTypeInfo().IsGenericType&& type.GetGenericTypeDefinition() == Globals.TypeOfNullable) { nullables++; type = type.GetGenericArguments()[0]; } PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(type); if ((primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) || nullables != 0 || type.GetTypeInfo().IsValueType) { LocalBuilder objectId = _ilg.DeclareLocal(Globals.TypeOfString, "objectIdRead"); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.ReadAttributesMethod, _xmlReaderArg); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.ReadIfNullOrRefMethod, _xmlReaderArg, type, DataContract.IsTypeSerializable(type)); _ilg.Stloc(objectId); // Deserialize null _ilg.If(objectId, Cmp.EqualTo, Globals.NullObjectId); if (nullables != 0) { _ilg.LoadAddress(value); _ilg.InitObj(value.LocalType); } else if (type.GetTypeInfo().IsValueType) { ThrowSerializationException(SR.Format(SR.ValueTypeCannotBeNull, DataContract.GetClrTypeFullName(type))); } else { _ilg.Load(null); _ilg.Stloc(value); } // Deserialize value // Compare against Globals.NewObjectId, which is set to string.Empty _ilg.ElseIfIsEmptyString(objectId); _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetObjectIdMethod); _ilg.Stloc(objectId); if (type.GetTypeInfo().IsValueType) { _ilg.IfNotIsEmptyString(objectId); ThrowSerializationException(SR.Format(SR.ValueTypeCannotHaveId, DataContract.GetClrTypeFullName(type))); _ilg.EndIf(); } if (nullables != 0) { nullableValue = value; value = _ilg.DeclareLocal(type, "innerValueRead"); } if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) { _ilg.Call(_xmlReaderArg, primitiveContract.XmlFormatReaderMethod); _ilg.Stloc(value); if (!type.GetTypeInfo().IsValueType) { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.AddNewObjectMethod, value); } } else { InternalDeserialize(value, type, name); } // Deserialize ref _ilg.Else(); if (type.GetTypeInfo().IsValueType) { ThrowSerializationException(SR.Format(SR.ValueTypeCannotHaveRef, DataContract.GetClrTypeFullName(type))); } else { _ilg.Call(_contextArg, XmlFormatGeneratorStatics.GetExistingObjectMethod, objectId, type, name, string.Empty); _ilg.ConvertValue(Globals.TypeOfObject, type); _ilg.Stloc(value); } _ilg.EndIf(); if (nullableValue != null) { _ilg.If(objectId, Cmp.NotEqualTo, Globals.NullObjectId); WrapNullableObject(value, nullableValue, nullables); _ilg.EndIf(); value = nullableValue; } } else { InternalDeserialize(value, type, name); } return(value); }
protected override int ReflectionWriteMembers(XmlWriterDelegator xmlWriter, object obj, XmlObjectSerializerWriteContext context, ClassDataContract classContract, ClassDataContract derivedMostClassContract, int childElementIndex, XmlDictionaryString[] memberNames) { int memberCount = (classContract.BaseContract == null) ? 0 : ReflectionWriteMembers(xmlWriter, obj, context, classContract.BaseContract, derivedMostClassContract, childElementIndex, memberNames); childElementIndex += memberCount; Type classType = classContract.UnadaptedClassType; context.IncrementItemCount(classContract.Members.Count); for (int i = 0; i < classContract.Members.Count; i++, memberCount++) { DataMember member = classContract.Members[i]; Type memberType = member.MemberType; if (member.IsGetOnlyCollection) { context.StoreIsGetOnlyCollection(); } bool shouldWriteValue = true; object memberValue = null; if (!member.EmitDefaultValue) { memberValue = ReflectionGetMemberValue(obj, member); object defaultValue = XmlFormatGeneratorStatics.GetDefaultValue(memberType); if ((memberValue == null && defaultValue == null) || (memberValue != null && memberValue.Equals(defaultValue))) { shouldWriteValue = false; if (member.IsRequired) { XmlObjectSerializerWriteContext.ThrowRequiredMemberMustBeEmitted(member.Name, classContract.UnderlyingType); } } } if (shouldWriteValue) { if (memberValue == null) { memberValue = ReflectionGetMemberValue(obj, member); } bool requiresNameAttribute = DataContractJsonSerializerImpl.CheckIfXmlNameRequiresMapping(classContract.MemberNames[i]); PrimitiveDataContract primitiveContract = member.MemberPrimitiveContract; if (requiresNameAttribute || !ReflectionTryWritePrimitive(xmlWriter, context, memberType, memberValue, memberNames[i + childElementIndex] /*name*/, null /*ns*/, primitiveContract)) { // Note: DataContractSerializer has member-conflict logic here to deal with the schema export // requirement that the same member can't be of two different types. if (requiresNameAttribute) { XmlObjectSerializerWriteContextComplexJson.WriteJsonNameWithMapping(xmlWriter, memberNames, i + childElementIndex); } else { ReflectionWriteStartElement(xmlWriter, memberNames[i + childElementIndex]); } ReflectionWriteValue(xmlWriter, context, memberType, memberValue, false /*writeXsiType*/, primitiveContractForParamType: null); ReflectionWriteEndElement(xmlWriter); } if (classContract.HasExtensionData) { context.WriteExtensionData(xmlWriter, ((IExtensibleDataObject)obj).ExtensionData, memberCount); } } } return(memberCount); }
object ReadValue(Type type, string name) { var valueType = type; object value = null; bool shouldAssignNullableValue = false; int nullables = 0; while (type.IsGenericType && type.GetGenericTypeDefinition() == Globals.TypeOfNullable) { nullables++; type = type.GetGenericArguments() [0]; } PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(type); if ((primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) || nullables != 0 || type.IsValueType) { context.ReadAttributes(xmlReader); string objectId = context.ReadIfNullOrRef(xmlReader, type, DataContract.IsTypeSerializable(type)); // Deserialize null if (objectId == Globals.NullObjectId) { if (nullables != 0) { value = Activator.CreateInstance(valueType); } else if (type.IsValueType) { throw new SerializationException(SR.GetString(SR.ValueTypeCannotBeNull, DataContract.GetClrTypeFullName(type))); } else { value = null; } } else if (objectId == string.Empty) { // Deserialize value // Compare against Globals.NewObjectId, which is set to string.Empty objectId = context.GetObjectId(); if (type.IsValueType) { if (!string.IsNullOrEmpty(objectId)) { throw new SerializationException(SR.GetString(SR.ValueTypeCannotHaveId, DataContract.GetClrTypeFullName(type))); } } object innerValueRead = null; if (nullables != 0) { shouldAssignNullableValue = true; } if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) { value = primitiveContract.XmlFormatReaderMethod.Invoke(xmlReader, new object [0]); if (!type.IsValueType) { context.AddNewObject(value); } } else { value = InternalDeserialize(type, name); } } else { // Deserialize ref if (type.IsValueType) { throw new SerializationException(SR.GetString(SR.ValueTypeCannotHaveRef, DataContract.GetClrTypeFullName(type))); } else { value = CodeInterpreter.ConvertValue(context.GetExistingObject(objectId, type, name, string.Empty), Globals.TypeOfObject, type); } } if (shouldAssignNullableValue) { if (objectId != Globals.NullObjectId) { value = WrapNullableObject(type, value, valueType, nullables); } } } else { value = InternalDeserialize(type, name); } return(value); }
void WriteValue(Type memberType, object memberValue) { Pointer memberValueRefPointer = null; if (memberType.IsPointer) { memberValueRefPointer = (Pointer)JsonFormatGeneratorStatics.BoxPointer.Invoke(null, new object [] { memberValue, memberType }); } bool isNullableOfT = (memberType.IsGenericType && memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable); if (memberType.IsValueType && !isNullableOfT) { PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType); if (primitiveContract != null) { primitiveContract.XmlFormatContentWriterMethod.Invoke(writer, new object [] { memberValue }); } else { InternalSerialize(XmlFormatGeneratorStatics.InternalSerializeMethod, () => memberValue, memberType, false); } } else { bool isNull; if (isNullableOfT) { memberValue = UnwrapNullableObject(() => memberValue, ref memberType, out isNull); //Leaves !HasValue on stack } else { isNull = memberValue == null; } if (isNull) { XmlFormatGeneratorStatics.WriteNullMethod.Invoke(context, new object [] { writer, memberType, DataContract.IsTypeSerializable(memberType) }); } else { PrimitiveDataContract primitiveContract = PrimitiveDataContract.GetPrimitiveDataContract(memberType); if (primitiveContract != null && primitiveContract.UnderlyingType != Globals.TypeOfObject) { if (isNullableOfT) { primitiveContract.XmlFormatContentWriterMethod.Invoke(writer, new object [] { memberValue }); } else { primitiveContract.XmlFormatContentWriterMethod.Invoke(context, new object [] { writer, memberValue }); } } else { bool isNull2 = false; if (memberType == Globals.TypeOfObject || //boxed Nullable<T> memberType == Globals.TypeOfValueType || ((IList)Globals.TypeOfNullable.GetInterfaces()).Contains(memberType)) { var unwrappedMemberValue = CodeInterpreter.ConvertValue(memberValue, memberType.GetType(), Globals.TypeOfObject); memberValue = unwrappedMemberValue; isNull2 = memberValue == null; } if (isNull2) { XmlFormatGeneratorStatics.WriteNullMethod.Invoke(context, new object [] { writer, memberType, DataContract.IsTypeSerializable(memberType) }); } else { InternalSerialize((isNullableOfT ? XmlFormatGeneratorStatics.InternalSerializeMethod : XmlFormatGeneratorStatics.InternalSerializeReferenceMethod), () => memberValue, memberType, false); } } } } }