/// <summary> /// Save an object to Xml. /// </summary> /// <param name="value">The object to serialize.</param> /// <param name="writer">The XmlWriter object to save to.</param> public static void SaveToXml(object value, XmlWriter writer) { Type type = value.GetType(); XmlElementNameAttribute[] xmlElementNameAttributes = (XmlElementNameAttribute[])type.GetCustomAttributes(typeof(XmlElementNameAttribute), true); string elementName = (xmlElementNameAttributes.Length > 0 ? xmlElementNameAttributes[0].XmlElementName : type.Name); writer.WriteStartElement(elementName); PropertyInfo[] properties = type.GetProperties(); foreach (PropertyInfo property in properties) { Type propertyType = property.PropertyType; XmlIgnoreAttribute[] ignoreAttributes = (XmlIgnoreAttribute[])property.GetCustomAttributes(typeof(XmlIgnoreAttribute), true); if (ignoreAttributes.Length == 0) { XmlAttributeNameAttribute[] xmlAttributeNameAttributes = (XmlAttributeNameAttribute[])property.GetCustomAttributes(typeof(XmlAttributeNameAttribute), true); string attributeName = (xmlAttributeNameAttributes.Length > 0 ? xmlAttributeNameAttributes[0].XmlAttributeName : property.Name); object propertyValue = property.GetValue(value, null); if (propertyValue != null) { XmlHasChildElementsAttribute[] xmlHasChildElementsAttributes = (XmlHasChildElementsAttribute[])propertyType.GetCustomAttributes(typeof(XmlHasChildElementsAttribute), true); if ((xmlHasChildElementsAttributes.Length > 0) && (xmlHasChildElementsAttributes[0].HasChildElements)) { SaveToXml(propertyValue, writer); } else { XmlCollectionAttribute[] xmlCollectionAttributes = (XmlCollectionAttribute[])property.GetCustomAttributes(typeof(XmlCollectionAttribute), true); if (xmlCollectionAttributes.Length > 0) { if ((propertyValue is IList == false)) { throw new Exception("Property marked as XmlCollection but does not implement IList."); } XmlCollectionAttribute xmlCollectionAttribute = xmlCollectionAttributes[0]; writer.WriteStartElement(xmlCollectionAttribute.CollectionElementName); IList listValue = (IList)propertyValue; foreach (object childValue in listValue) { SaveToXml(childValue, writer); } writer.WriteEndElement(); } else { writer.WriteAttributeString(attributeName, (propertyValue != null ? XmlHelper.ToString(propertyValue) : String.Empty)); } } } } } writer.WriteEndElement(); }
/// <summary> /// Parse an Xml element into a specifed type. /// </summary> /// <param name="elementNode">The xml node containing the element to parse.</param> /// <param name="elementType">The type of object to deserialize into.</param> /// <returns>The instance of the newly deserialized object.</returns> public static object ParseElement(XmlNode elementNode, Type elementType) { ConstructorInfo constructorInfo = elementType.GetConstructor(new Type[] { }); object elementObject = constructorInfo.Invoke(null); XmlCollectionAttribute[] xmlCollectionClassAttributes = (XmlCollectionAttribute[])elementType.GetCustomAttributes(typeof(XmlCollectionAttribute), true); if (xmlCollectionClassAttributes.Length > 0) { if ((elementObject is IList == false)) { throw new Exception("Class marked as XmlCollection but type does not implement IList."); } XmlCollectionAttribute xmlCollectionClassAttribute = xmlCollectionClassAttributes[0]; if ((elementNode.Name == xmlCollectionClassAttribute.CollectionElementName) && (elementNode.HasChildNodes)) { IList listObject = (IList)elementObject; foreach (XmlNode childNode in elementNode.ChildNodes) { if (childNode.Name == xmlCollectionClassAttribute.ItemElementName) { object childValue = ParseElement(childNode, xmlCollectionClassAttribute.ItemType); listObject.Add(childValue); } } } } else { PropertyInfo[] properties = elementType.GetProperties(); foreach (PropertyInfo property in properties) { Type propertyType = property.PropertyType; XmlIgnoreAttribute[] ignoreAttributes = (XmlIgnoreAttribute[])property.GetCustomAttributes(typeof(XmlIgnoreAttribute), true); if (ignoreAttributes.Length > 0) { continue; } bool isRequired; bool invokeConstructor; object defaultValue; XmlRequiredAttribute[] xmlRequiredAttributes = (XmlRequiredAttribute[])property.GetCustomAttributes(typeof(XmlRequiredAttribute), true); if (xmlRequiredAttributes.Length > 0) { XmlRequiredAttribute xmlRequiredAttribute = xmlRequiredAttributes[0]; isRequired = xmlRequiredAttribute.IsRequired; invokeConstructor = xmlRequiredAttribute.InvokeConstructor; defaultValue = xmlRequiredAttribute.DefaultValue; } else { isRequired = true; invokeConstructor = false; defaultValue = null; } object value; XmlHasChildElementsAttribute[] xmlHasChildElementsAttributes = (XmlHasChildElementsAttribute[])propertyType.GetCustomAttributes(typeof(XmlHasChildElementsAttribute), true); if ((xmlHasChildElementsAttributes.Length > 0) && (xmlHasChildElementsAttributes[0].HasChildElements)) { XmlElementNameAttribute[] xmlElementNameAttributes = (XmlElementNameAttribute[])propertyType.GetCustomAttributes(typeof(XmlElementNameAttribute), true); string childElementName = (xmlElementNameAttributes.Length > 0 ? xmlElementNameAttributes[0].XmlElementName : property.Name); XmlNode childElementNode = XmlHelper.GetChildNode(elementNode, childElementName); if (childElementNode != null) { value = ParseElement(childElementNode, propertyType); } else { if (isRequired) { throw new Exception("Child element [" + childElementName + "] not found."); } if (invokeConstructor) { ConstructorInfo childElementConstructorInfo = propertyType.GetConstructor(new Type[] { }); value = childElementConstructorInfo.Invoke(null); } else { value = defaultValue; } } } else { XmlAttributeNameAttribute[] xmlAttributeNameAttributes = (XmlAttributeNameAttribute[])property.GetCustomAttributes(typeof(XmlAttributeNameAttribute), true); string attributeName = (xmlAttributeNameAttributes.Length > 0 ? xmlAttributeNameAttributes[0].XmlAttributeName : property.Name); value = XmlHelper.GetAttribute(elementNode, attributeName, propertyType, isRequired, defaultValue); if ((value == defaultValue) && (isRequired == false) && (invokeConstructor)) { if (propertyType.IsValueType) { value = Activator.CreateInstance(propertyType); } else { ConstructorInfo propertyConstructorInfo = propertyType.GetConstructor(new Type[] { }); value = propertyConstructorInfo.Invoke(null); } } } XmlCollectionAttribute[] xmlCollectionAttributes = (XmlCollectionAttribute[])property.GetCustomAttributes(typeof(XmlCollectionAttribute), true); if (xmlCollectionAttributes.Length > 0) { if ((value is IList == false)) { throw new Exception("Property marked as XmlCollection but type does not implement IList."); } XmlCollectionAttribute xmlCollectionAttribute = xmlCollectionAttributes[0]; XmlNode xmlCollectionNode = XmlHelper.GetChildNode(elementNode, xmlCollectionAttribute.CollectionElementName); if ((xmlCollectionNode != null) && (xmlCollectionNode.HasChildNodes)) { IList listValue = (IList)value; foreach (XmlNode childNode in xmlCollectionNode.ChildNodes) { if (childNode.Name == xmlCollectionAttribute.ItemElementName) { object childValue = ParseElement(childNode, xmlCollectionAttribute.ItemType); listValue.Add(childValue); } } } } property.SetValue(elementObject, value, null); } } return(elementObject); }