/// <summary> /// Writes the XML element to the xml element. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="elementName">Name of the element.</param> /// <param name="memberValue">The member value.</param> /// <param name="modelType">Type of the model.</param> private void WriteXmlElement(ISerializationContext <XmlSerializationContextInfo> context, XElement element, string elementName, MemberValue memberValue, Type modelType) { var contextInfo = context.Context; var namespacePrefix = GetNamespacePrefix(); var stringBuilder = new StringBuilder(); var xmlWriterSettings = new XmlWriterSettings(); XmlNamespace xmlNamespace = null; xmlWriterSettings.OmitXmlDeclaration = true; xmlWriterSettings.CheckCharacters = false; xmlWriterSettings.ConformanceLevel = ConformanceLevel.Fragment; xmlWriterSettings.NamespaceHandling = NamespaceHandling.OmitDuplicates; using (var xmlWriter = XmlWriter.Create(stringBuilder, xmlWriterSettings)) { var memberTypeToSerialize = memberValue.Value != null?memberValue.Value.GetType() : typeof(object); var serializer = _dataContractSerializerFactory.GetDataContractSerializer(modelType, memberTypeToSerialize, elementName, null, memberValue.Value); if (memberValue.Value == null) { xmlWriter.WriteStartElement(elementName); xmlWriter.WriteAttributeString(namespacePrefix, "IsNull", null, "true"); xmlWriter.WriteEndElement(); } else { ReferenceInfo referenceInfo = null; bool serializeElement = true; var isClassType = TypeHelper.IsClassType(memberTypeToSerialize); if (isClassType) { var referenceManager = context.ReferenceManager; referenceInfo = referenceManager.GetInfo(memberValue.Value); if (!referenceInfo.IsFirstUsage) { Log.Debug("Existing reference detected for element type '{0}' with id '{1}', only storing id", memberTypeToSerialize.GetSafeFullName(), referenceInfo.Id); //serializer.WriteStartObject(xmlWriter, memberValue.Value); xmlWriter.WriteStartElement(elementName); xmlWriter.WriteAttributeString(namespacePrefix, GraphRefId, null, referenceInfo.Id.ToString()); //serializer.WriteEndObject(xmlWriter); xmlWriter.WriteEndElement(); serializeElement = false; } } if (serializeElement) { //var xmlSerializer = new System.Xml.Serialization.XmlSerializer(memberTypeToSerialize, namespacePrefix); //xmlSerializer.Serialize(xmlWriter, memberValue.Value); xmlWriter.WriteStartElement(elementName); xmlNamespace = _xmlNamespaceManager.GetNamespace(memberTypeToSerialize, namespacePrefix); if (xmlNamespace != null) { xmlWriter.WriteAttributeString("xmlns", xmlNamespace.Prefix, null, xmlNamespace.Uri); } if (referenceInfo != null) { xmlWriter.WriteAttributeString(namespacePrefix, GraphId, null, referenceInfo.Id.ToString()); } if (memberTypeToSerialize != memberValue.Type) { var memberTypeToSerializerName = TypeHelper.GetTypeName(memberTypeToSerialize.FullName); xmlWriter.WriteAttributeString(namespacePrefix, "type", null, memberTypeToSerializerName); } serializer.WriteObjectContent(xmlWriter, memberValue.Value); xmlWriter.WriteEndElement(); } } } EnsureNamespaceInXmlDocument(element, xmlNamespace); var childContent = stringBuilder.ToString(); var childElement = XElement.Parse(childContent); element.Add(childElement); }
/// <summary> /// Initializes a new instance of the <see cref="MemberSerializationEventArgs" /> class. /// </summary> /// <param name="serializationContext">The serialization context.</param> /// <param name="memberValue">The member value.</param> public MemberSerializationEventArgs(ISerializationContext serializationContext, MemberValue memberValue) : base(serializationContext) { MemberValue = memberValue; // Note: no check for null to improve performance }
/// <summary> /// Gets the object from XML attribute. /// </summary> /// <remarks> /// Note that this method can cause exceptions. The caller will handle them. /// </remarks> /// <param name="attribute">The attribute.</param> /// <param name="memberValue">The property data.</param> /// <returns>Object or <c>null</c>.</returns> private object GetObjectFromXmlAttribute(XAttribute attribute, MemberValue memberValue) { var value = attribute.Value; return(StringToObjectHelper.ToRightType(memberValue.Type, value)); }
/// <summary> /// Gets the object from XML element. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="memberValue">The member value.</param> /// <param name="modelType">Type of the model.</param> /// <returns>Object or <c>null</c>.</returns> /// <remarks>Note that this method can cause exceptions. The caller will handle them.</remarks> private object GetObjectFromXmlElement(ISerializationContext <XmlSerializationContextInfo> context, XElement element, MemberValue memberValue, Type modelType) { object value = null; string xmlName = element.Name.LocalName; var propertyTypeToDeserialize = memberValue.Type; var isNullAttribute = element.Attribute("IsNull"); var isNull = (isNullAttribute != null) ? StringToObjectHelper.ToBool(isNullAttribute.Value) : false; if (isNull) { return(null); } var graphRefIdAttribute = element.Attribute(GraphRefId); if (graphRefIdAttribute != null) { var graphId = int.Parse(graphRefIdAttribute.Value); var referenceManager = context.ReferenceManager; var referenceInfo = referenceManager.GetInfoById(graphId); if (referenceInfo == null) { Log.Error("Expected to find graph object with id '{0}' in ReferenceManager, but it was not found. Defaulting value for member '{1}' to null", graphId, element.Name); return(null); } return(referenceInfo.Instance); } var typeAttribute = element.Attribute("type"); // .GetAttribute("type", "http://catel.codeplex.com"); var attributeValue = (typeAttribute != null) ? typeAttribute.Value : null; if (!string.IsNullOrEmpty(attributeValue)) { var typeToDeserialize = TypeCache.GetTypeWithoutAssembly(attributeValue); if (typeToDeserialize != null) { Log.Debug("Property type for property '{0}' is '{1}' but found type info that it should be deserialized as '{2}'", memberValue.Name, memberValue.Type.FullName, attributeValue); propertyTypeToDeserialize = typeToDeserialize; } else { Log.Warning("Property type for property '{0}' is '{1}' but found type info that it should be deserialized as '{2}'. Unfortunately the type cannot be found so the deserialization will probably fail.", memberValue.Name, memberValue.Type.FullName, attributeValue); } } //var xmlSerializationContextInfo = context.Context; //var serializer = xmlSerializationContextInfo.GetDataContractSerializer(); var serializer = _dataContractSerializerFactory.GetDataContractSerializer(modelType, propertyTypeToDeserialize, xmlName); using (var xmlReader = element.CreateReader()) { value = serializer.ReadObject(xmlReader, false); } return(value); }
/// <summary> /// Serializes the member. /// </summary> /// <param name="context">The context.</param> /// <param name="memberValue">The member value.</param> protected override void SerializeMember(ISerializationContext <XmlSerializationContextInfo> context, MemberValue memberValue) { var modelType = context.ModelType; var element = context.Context.Element; var propertyDataManager = PropertyDataManager.Default; if (propertyDataManager.IsPropertyNameMappedToXmlAttribute(modelType, memberValue.Name)) { var attributeName = propertyDataManager.MapPropertyNameToXmlAttributeName(modelType, memberValue.Name); Log.Debug("Serializing property {0}.{1} as xml attribute '{2}'", modelType.FullName, memberValue.Name, attributeName); WriteXmlAttribute(element, attributeName, memberValue); } else { var elementName = memberValue.Name; if (propertyDataManager.IsPropertyNameMappedToXmlElement(modelType, memberValue.Name)) { elementName = propertyDataManager.MapPropertyNameToXmlElementName(modelType, memberValue.Name); } Log.Debug("Serializing property {0}.{1} as xml element '{2}'", modelType.FullName, memberValue.Name, elementName); WriteXmlElement(context, element, elementName, memberValue, modelType); } }
/// <summary> /// Deserializes the member. /// </summary> /// <param name="context">The context.</param> /// <param name="memberValue">The member value.</param> /// <returns>The <see cref="SerializationObject"/> representing the deserialized value or result.</returns> protected override SerializationObject DeserializeMember(ISerializationContext <XmlSerializationContextInfo> context, MemberValue memberValue) { var modelType = context.ModelType; var element = context.Context.Element; try { var propertyDataManager = PropertyDataManager.Default; if (propertyDataManager.IsPropertyNameMappedToXmlAttribute(modelType, memberValue.Name)) { var mappedPropertyName = propertyDataManager.MapPropertyNameToXmlAttributeName(modelType, memberValue.Name); Log.Debug("Deserializing property {0}.{1} as xml attribute '{2}'", modelType.FullName, memberValue.Name, mappedPropertyName); foreach (var childAttribute in element.Attributes()) { if (string.Equals(mappedPropertyName, childAttribute.Name.LocalName)) { var value = GetObjectFromXmlAttribute(childAttribute, memberValue); return(SerializationObject.SucceededToDeserialize(modelType, memberValue.MemberGroup, memberValue.Name, value)); } } } else { string elementName = memberValue.Name; if (propertyDataManager.IsPropertyNameMappedToXmlElement(modelType, memberValue.Name)) { elementName = propertyDataManager.MapPropertyNameToXmlElementName(modelType, memberValue.Name); } Log.Debug("Deserializing property {0}.{1} as xml element '{2}'", modelType.FullName, memberValue.Name, elementName); foreach (var childElement in element.Elements()) { if (string.Equals(elementName, childElement.Name.LocalName)) { var value = GetObjectFromXmlElement(context, childElement, memberValue, modelType); return(SerializationObject.SucceededToDeserialize(modelType, memberValue.MemberGroup, memberValue.Name, value)); } } } } catch (Exception) { // Swallow } return(SerializationObject.FailedToDeserialize(modelType, memberValue.MemberGroup, memberValue.Name)); }
public override bool ShouldIgnoreMember(ISerializationContext context, IModel model, MemberValue memberValue) { if (string.Equals(memberValue.Name, "IgnoredMember")) { return(true); } return(false); }
/// <summary> /// Deserializes the member. /// </summary> /// <param name="context">The context.</param> /// <param name="memberValue">The member value.</param> /// <returns>The <see cref="SerializationObject"/> representing the deserialized value or result.</returns> protected override SerializationObject DeserializeMember(ISerializationContext <BinarySerializationContextInfo> context, MemberValue memberValue) { var serializationContext = context.Context; var memberValues = serializationContext.MemberValues; var finalMembervalue = (from x in memberValues where string.Equals(x.Name, memberValue.Name, StringComparison.Ordinal) select x).FirstOrDefault(); if (finalMembervalue != null) { return(SerializationObject.SucceededToDeserialize(context.ModelType, memberValue.MemberGroup, memberValue.Name, finalMembervalue.Value)); } return(SerializationObject.FailedToDeserialize(context.ModelType, memberValue.MemberGroup, memberValue.Name)); }
/// <summary> /// Serializes the member. /// </summary> /// <param name="context">The context.</param> /// <param name="memberValue">The member value.</param> protected override void SerializeMember(ISerializationContext <BinarySerializationContextInfo> context, MemberValue memberValue) { var serializationContext = context.Context; var memberValues = serializationContext.MemberValues; if (memberValue.MemberGroup == SerializationMemberGroup.Dictionary) { memberValue.Value = ConvertDictionaryToCollection(memberValue.Value); } memberValues.Add(memberValue); }
/// <summary> /// Writes the XML element to the xml element. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="elementName">Name of the element.</param> /// <param name="memberValue">The member value.</param> /// <param name="modelType">Type of the model.</param> private void WriteXmlElement(ISerializationContext <XmlSerializationContextInfo> context, XElement element, string elementName, MemberValue memberValue, Type modelType) { var contextInfo = context.Context; var namespacePrefix = GetNamespacePrefix(); var stringBuilder = new StringBuilder(); var xmlWriterSettings = new XmlWriterSettings(); XmlNamespace xmlNamespace = null; xmlWriterSettings.OmitXmlDeclaration = true; xmlWriterSettings.CheckCharacters = false; xmlWriterSettings.ConformanceLevel = ConformanceLevel.Fragment; xmlWriterSettings.NamespaceHandling = NamespaceHandling.OmitDuplicates; #if XAMARIN var defaultNamespace = "http://www.w3.org/2000/xmlns/"; #endif using (var xmlWriter = XmlWriter.Create(stringBuilder, xmlWriterSettings)) { if (memberValue.Value == null) { xmlWriter.WriteStartElement(elementName); #if XAMARIN xmlWriter.WriteAttributeString("xmlns", namespacePrefix, defaultNamespace, "http://catel.codeplex.com"); #endif xmlWriter.WriteAttributeString(namespacePrefix, "IsNull", null, "true"); xmlWriter.WriteEndElement(); } else { var memberTypeToSerialize = memberValue.GetBestMemberType(); var serializer = _dataContractSerializerFactory.GetDataContractSerializer(modelType, memberTypeToSerialize, elementName, null, null); ReferenceInfo referenceInfo = null; var serializeElement = true; if (memberValue.MemberGroup != SerializationMemberGroup.Collection) { var isClassType = memberTypeToSerialize.IsClassType(); if (isClassType) { var referenceManager = context.ReferenceManager; referenceInfo = referenceManager.GetInfo(memberValue.Value); if (!referenceInfo.IsFirstUsage) { // Note: we don't want to call GetSafeFullName if we don't have to if (LogManager.IsDebugEnabled ?? false) { Log.Debug("Existing reference detected for element type '{0}' with id '{1}', only storing id", memberTypeToSerialize.GetSafeFullName(), referenceInfo.Id); } //serializer.WriteStartObject(xmlWriter, memberValue.Value); xmlWriter.WriteStartElement(elementName); xmlWriter.WriteAttributeString(namespacePrefix, GraphRefId, null, referenceInfo.Id.ToString()); //serializer.WriteEndObject(xmlWriter); xmlWriter.WriteEndElement(); serializeElement = false; } } } if (serializeElement) { //var xmlSerializer = new System.Xml.Serialization.XmlSerializer(memberTypeToSerialize, namespacePrefix); //xmlSerializer.Serialize(xmlWriter, memberValue.Value); xmlWriter.WriteStartElement(elementName); xmlNamespace = _xmlNamespaceManager.GetNamespace(memberTypeToSerialize, namespacePrefix); if (xmlNamespace != null) { xmlWriter.WriteAttributeString("xmlns", xmlNamespace.Prefix, null, xmlNamespace.Uri); } if (referenceInfo != null) { xmlWriter.WriteAttributeString(namespacePrefix, GraphId, null, referenceInfo.Id.ToString()); } if (memberTypeToSerialize != memberValue.MemberType) { var memberTypeToSerializerName = TypeHelper.GetTypeName(memberTypeToSerialize.FullName); xmlWriter.WriteAttributeString(namespacePrefix, "type", null, memberTypeToSerializerName); } // In special cases, we need to write our own collection items. One case is where a custom ModelBase // implements IList and gets inside a StackOverflow var serialized = false; if (ShouldSerializeModelAsCollection(memberValue.GetBestMemberType())) { var collection = memberValue.Value as IEnumerable; if (collection != null) { foreach (var item in collection) { var subItemElementName = GetXmlElementName(item.GetType(), item, null); xmlWriter.WriteStartElement(subItemElementName); serializer.WriteObjectContent(xmlWriter, item); xmlWriter.WriteEndElement(); } serialized = true; } } if (!serialized) { serializer.WriteObjectContent(xmlWriter, memberValue.Value); } xmlWriter.WriteEndElement(); } } } EnsureNamespaceInXmlDocument(element, xmlNamespace); var childContent = stringBuilder.ToString(); var childElement = XElement.Parse(childContent); element.Add(childElement); }
/// <summary> /// Gets the object from XML element. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="memberValue">The member value.</param> /// <param name="modelType">Type of the model.</param> /// <returns>Object or <c>null</c>.</returns> /// <remarks>Note that this method can cause exceptions. The caller will handle them.</remarks> private object GetObjectFromXmlElement(ISerializationContext <XmlSerializationContextInfo> context, XElement element, MemberValue memberValue, Type modelType) { object value = null; var xmlName = element.Name.LocalName; var propertyTypeToDeserialize = memberValue.MemberType; var isNullAttribute = element.Attribute("IsNull"); var isNull = (isNullAttribute != null) ? StringToObjectHelper.ToBool(isNullAttribute.Value) : false; if (isNull) { return(null); } var graphRefIdAttribute = element.Attribute(GraphRefId); if (graphRefIdAttribute != null) { var graphId = int.Parse(graphRefIdAttribute.Value); var referenceManager = context.ReferenceManager; var referenceInfo = referenceManager.GetInfoById(graphId); if (referenceInfo == null) { Log.Error("Expected to find graph object with id '{0}' in ReferenceManager, but it was not found. Defaulting value for member '{1}' to null", graphId, element.Name); return(null); } return(referenceInfo.Instance); } var typeAttribute = element.Attribute("type"); // .GetAttribute("type", "http://catel.codeplex.com"); var attributeValue = (typeAttribute != null) ? typeAttribute.Value : null; if (!string.IsNullOrEmpty(attributeValue)) { var typeToDeserialize = TypeCache.GetTypeWithoutAssembly(attributeValue); if (typeToDeserialize != null && propertyTypeToDeserialize != typeToDeserialize) { Log.Debug("Property type for property '{0}' is '{1}' but found type info that it should be deserialized as '{2}'", memberValue.Name, memberValue.MemberType.FullName, attributeValue); propertyTypeToDeserialize = typeToDeserialize; } else { Log.Warning("Property type for property '{0}' is '{1}' but found type info that it should be deserialized as '{2}'. Unfortunately the type cannot be found so the deserialization will probably fail.", memberValue.Name, memberValue.MemberType.FullName, attributeValue); } } var isDeserialized = false; if (ShouldSerializeModelAsCollection(propertyTypeToDeserialize)) { var collection = value as IList; if (collection == null) { collection = CreateModelInstance(propertyTypeToDeserialize) as IList; } if (collection == null) { throw Log.ErrorAndCreateException <NotSupportedException>("Cannot deserialize type '{0}', it should implement IList in order to be deserialized", propertyTypeToDeserialize.GetSafeFullName()); } var realCollectionType = collection.GetType(); var childElementType = realCollectionType.GetCollectionElementType(); if (childElementType == null) { throw Log.ErrorAndCreateException <NotSupportedException>("Cannot deserialize type '{0}', could not determine the element type of the collection", propertyTypeToDeserialize.GetSafeFullName()); } var serializer = _dataContractSerializerFactory.GetDataContractSerializer(propertyTypeToDeserialize, childElementType, xmlName, null, null); var childElements = element.Elements(); foreach (var childElement in childElements) { using (var xmlReader = childElement.CreateReader()) { var childValue = serializer.ReadObject(xmlReader, false); if (childValue != null) { collection.Add(childValue); } } } value = collection; isDeserialized = true; } if (!isDeserialized) { var serializer = _dataContractSerializerFactory.GetDataContractSerializer(modelType, propertyTypeToDeserialize, xmlName, null, null); using (var xmlReader = element.CreateReader()) { value = serializer.ReadObject(xmlReader, false); } } // Fix for CTL-555 var graphIdAttribute = element.Attribute(GraphId); if (graphIdAttribute != null) { var graphId = int.Parse(graphIdAttribute.Value); var referenceManager = context.ReferenceManager; referenceManager.RegisterManually(graphId, value); } return(value); }
/// <summary> /// Serializes the member. /// </summary> /// <param name="context">The context.</param> /// <param name="memberValue">The member value.</param> protected override void SerializeMember(ISerializationContext <XmlSerializationContextInfo> context, MemberValue memberValue) { var modelType = context.ModelType; var element = context.Context.Element; if (memberValue.MemberGroup == SerializationMemberGroup.SimpleRootObject) { WriteXmlElement(context, element, memberValue.Name, memberValue, memberValue.MemberType); return; } if (ShouldSerializeAsDictionary(memberValue)) { // TODO: For now only support top-level dictionaries if (context.Depth == 0) { var collection = ConvertDictionaryToCollection(memberValue.Value); if (collection != null) { Serialize(collection, context.Context); } return; } } var propertyDataManager = PropertyDataManager.Default; if (propertyDataManager.IsPropertyNameMappedToXmlAttribute(modelType, memberValue.Name)) { var attributeName = propertyDataManager.MapPropertyNameToXmlAttributeName(modelType, memberValue.Name); Log.Debug("Serializing property {0}.{1} as xml attribute '{2}'", modelType.FullName, memberValue.Name, attributeName); WriteXmlAttribute(element, attributeName, memberValue); } else { var elementName = memberValue.Name; if (propertyDataManager.IsPropertyNameMappedToXmlElement(modelType, memberValue.Name)) { elementName = propertyDataManager.MapPropertyNameToXmlElementName(modelType, memberValue.Name); } Log.Debug("Serializing property {0}.{1} as xml element '{2}'", modelType.FullName, memberValue.Name, elementName); WriteXmlElement(context, element, elementName, memberValue, modelType); } }