public void WriteXml(XmlWriter writer, object value, XmlSerializationContext context) { if (context.Member.MappingType != XmlMappingType.Element) { throw new XmlSerializationException($"XML mapping of \"{context.ValueType}\" must be Element."); } var collectionItem = GetCollectionItem(context); if (collectionItem == null) { throw new XmlSerializationException( $"XML contract of \"{context.ValueType}\" must contains collection item"); } Type lastItemType = null; XmlTypeContext typeContext = null; foreach (var item in (IEnumerable)value) { if (item == null) { context.WriteNull(writer, collectionItem.ValueType, collectionItem); } else { var member = (XmlMember)collectionItem; var shouldWriteTypeName = context.TryResolveValueType(item, ref member, out Type itemType); if (itemType != lastItemType) { typeContext = context.Settings.GetTypeContext(itemType); lastItemType = itemType; } writer.WriteStartElement(member.Name); if (shouldWriteTypeName) { context.WriteTypeName(writer, lastItemType); } context.WriteXml(writer, item, member, typeContext); writer.WriteEndElement(); } } }
public object ReadXml(XmlReader reader, XmlSerializationContext context) { if (context.Member.MappingType != XmlMappingType.Element) { throw new XmlSerializationException(string.Format("XML mapping of \"{0}\" must be Element.", context.ValueType)); } var item = GetCollectionItem(context); if (item == null) { throw new XmlSerializationException(string.Format("XML contract of \"{0}\" must contains item info", context.ValueType)); } var collectionProxy = CreateProxy(context.ValueType); if (!reader.IsEmptyElement) { Type lastItemType = null; XmlTypeContext typeContext = null; var itemInfo = new XmlItemInfo(item, reader.NameTable); reader.ReadStartElement(); var nodeType = reader.NodeType; while (nodeType != XmlNodeType.EndElement) { if (nodeType == XmlNodeType.Element) { var member = itemInfo.Match(reader); if (member != null) { var valueType = member.ValueType; if (context.ReadValueType(reader, ref valueType)) { if (lastItemType != valueType) { typeContext = context.Settings.GetTypeContext(valueType); lastItemType = valueType; } var value = context.ReadXml(reader, member, typeContext); collectionProxy.Add(value); } else { reader.Skip(); } } else { reader.Skip(); } } else { reader.Read(); } nodeType = reader.NodeType; } } reader.Read(); return(collectionProxy.GetResult()); }
public void WriteXml(XmlWriter writer, object value, XmlSerializationContext context) { if (context.Member.MappingType != XmlMappingType.Element) { throw new XmlSerializationException(string.Format("XML mapping of \"{0}\" must be Element.", context.ValueType)); } var collectionItem = GetCollectionItem(context); if (collectionItem == null) { throw new XmlSerializationException(string.Format("XML contract of \"{0}\" must contains collection item", context.ValueType)); } Type lastItemType = null; XmlTypeContext typeContext = null; foreach (var listItem in (IEnumerable)value) { object item = listItem; // ignore optional none and unwrap optional because we've already done that in XmlContractResolver.ResolveItem if (listItem is IAnyOptional optional) { if (!optional.HasValue) { if (context.Settings.NoneValueHandling == XmlNoneValueHandling.Ignore) { continue; } // Output default values for inner types var innerType = optional.GetInnerType(); var nullableInnerType = innerType.GetUnderlyingNullableType(); if (nullableInnerType != null) { context.WriteNull(writer, collectionItem.ValueType, collectionItem); continue; } else if (innerType.IsClass) { context.WriteNull(writer, collectionItem.ValueType, collectionItem); continue; } } item = optional.Value; } if (item == null) { context.WriteNull(writer, collectionItem.ValueType, collectionItem); continue; } var member = (XmlMember)collectionItem; var shouldWriteTypeName = context.TryResolveValueType(item, ref member, out Type itemType); if (itemType != lastItemType) { typeContext = context.Settings.GetTypeContext(itemType); lastItemType = itemType; } // start writing element context.WriteElement(writer, item, member, typeContext, itemType, shouldWriteTypeName); } }