internal static void PutValueConvertedToStringToXml( XDocument document, string value, Type deserializeAs, Mapping mapping, bool isArrayItem, bool emitTypeInfo, IXmlNamespaceResolver resolver) { if (value != null || mapping.IsXmlMandatory || isArrayItem) { var mappedElement = XmlOperations.GetOrCreateElement(document, mapping.ElementXPath, resolver); if (mappedElement == null) { throw new SerializationException( String.Format("Cannot serialize object. Could not find or create element with mapping XPath '{0}'.", mapping.ElementXPath)); } if (value == null) { value = String.Empty; } if (String.IsNullOrWhiteSpace(mapping.AttributeName)) { if (mapping.AsXml) { if (!String.IsNullOrWhiteSpace(value)) { var wrappingElement = XElement.Parse("<root>" + value + "</root>"); mappedElement.Add(wrappingElement.Elements()); } if (emitTypeInfo) { if (deserializeAs != null) { if (mappedElement.Attribute(Constants.TypeInfoAttributeName) != null) { throw new SerializationException( String.Format("Cannot serialize object with type information. Mapping XPath '{0}' is used by more than 1 value.", mapping.ElementXPath)); } mappedElement.Add(new XAttribute(Constants.TypeInfoAttributeName, deserializeAs.AssemblyQualifiedName.ToString())); } else { if (mappedElement.Attribute(Constants.NullValueAttributeName) != null) { throw new SerializationException( String.Format("Cannot serialize object with type information. Mapping XPath '{0}' is used by more than 1 value.", mapping.ElementXPath)); } mappedElement.Add(new XAttribute(Constants.NullValueAttributeName, "true")); } } } else if (isArrayItem) { var arrayItemElement = new XElement(mapping.ArrayItemElementName, value); if (emitTypeInfo) { if (deserializeAs != null) { arrayItemElement.Add(new XAttribute(Constants.TypeInfoAttributeName, deserializeAs.AssemblyQualifiedName.ToString())); } else { arrayItemElement.Add(new XAttribute(Constants.NullValueAttributeName, "true")); } } mappedElement.Add(arrayItemElement); } else { mappedElement.Value = value; if (emitTypeInfo) { if (deserializeAs != null) { if (mappedElement.Attribute(Constants.TypeInfoAttributeName) != null) { throw new SerializationException( String.Format("Cannot serialize object with type information. Mapping XPath '{0}' is used by more than 1 value.", mapping.ElementXPath)); } mappedElement.Add(new XAttribute(Constants.TypeInfoAttributeName, deserializeAs.AssemblyQualifiedName.ToString())); } else { if (mappedElement.Attribute(Constants.NullValueAttributeName) != null) { throw new SerializationException( String.Format("Cannot serialize object with type information. Mapping XPath '{0}' is used by more than 1 value.", mapping.ElementXPath)); } mappedElement.Add(new XAttribute(Constants.NullValueAttributeName, "true")); } } } } else { mappedElement.SetAttributeValue(XPathHelper.ConvertToXName(mapping.AttributeName, resolver), value); } } }
private static void LoadMembersFromXml( XDocument document, IXPathSerializable serializable, SerializableMemberInfo[] membersToLoad, MemberInfo[] useMembers, Mapping parentMapping, int version, IFormatProvider provider, XmlNamespaceManager resolver) { foreach (var member in membersToLoad) { // Skip non-serializable members if (member.GetSingleCustomAttribute <NotForSerializationAttribute>() != null) { continue; } // Check if the member is serializable in the current version int serializedFromVersion = 0; var versionAttribute = member.GetSingleCustomAttribute <SerializedFromVersionAttribute>(); if (versionAttribute != null) { serializedFromVersion = versionAttribute.Version; } if (version < serializedFromVersion) { continue; } var mapping = member.GetMapping(serializable.GetType(), parentMapping); var mappedElement = document.Root.XPathSelectElement(mapping.ElementXPath, resolver); bool mappedToAttributeWhichIsNotFound = !String.IsNullOrWhiteSpace(mapping.AttributeName) && (mappedElement == null || mappedElement.Attribute(XPathHelper.ConvertToXName(mapping.AttributeName, resolver)) == null); // Ensure mandatory xml elements/attributes are present if (mapping.IsXmlMandatory) { if (mappedElement == null) { throw new SerializationException( String.Format( "Cannot deserialize {0} '{1}', type '{2}'. Could not find the element with path '{3}'", member.MemeberTypeString, member.Name, serializable.GetType(), mapping.ElementXPath)); } else if (mappedToAttributeWhichIsNotFound) { throw new SerializationException( String.Format( "Cannot deserialize {0} '{1}', type '{2}'. Could not find the attribute '{3}' of the element with path '{4}'", member.MemeberTypeString, member.Name, serializable.GetType(), mapping.AttributeName, mapping.ElementXPath)); } } // Short-circuit for nulls if (mappedElement == null || mappedToAttributeWhichIsNotFound) { member.SetValue(serializable, null); continue; } if (string.IsNullOrWhiteSpace(mapping.AttributeName)) { var isNullAttribute = mappedElement.Attribute(Constants.NullValueAttributeName); if (isNullAttribute != null) { member.SetValue(serializable, null); continue; } } // Determine the type of the deserialized value Type emittedType = null; if (mappedElement != null && string.IsNullOrWhiteSpace(mapping.AttributeName)) { var typeAttribute = mappedElement.Attribute(Constants.TypeInfoAttributeName); if (typeAttribute != null) { emittedType = Type.GetType(typeAttribute.Value); // TODO: handle all kind of exceptions } } Type deserializeAs; if (emittedType != null) { deserializeAs = emittedType; } else { deserializeAs = member.MemberType; } var context = new SerializationContext( serializable, member, mapping, useMembers, deserializeAs, version: version, formatProvider: provider, resolver: resolver); if (deserializeAs.IsArray && !mapping.AsBase64) { LoadArrayMemberFromXml(mappedElement, context); } else if (typeof(IXPathSerializable).IsAssignableFrom(deserializeAs)) { LoadXPathSerializableMemberFromXml(document, context); } else { LoadSimpleMemberFromXml(mappedElement, context); } } }