-
-
Save Kraego/afc79bfc5a466f8c256bf5a5e15ee02a to your computer and use it in GitHub Desktop.
C# Dynamic extension methods for serializing to XML
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Reflection; | |
| using System.Xml; | |
| using System.Xml.Linq; | |
| public static class DynamicHelper | |
| { | |
| /// <summary> | |
| /// Defines the simple types that is directly writeable to XML. | |
| /// </summary> | |
| private static readonly Type[] _writeTypes = new[] { typeof(string), typeof(DateTime), typeof(Enum), typeof(decimal), typeof(Guid) }; | |
| /// <summary> | |
| /// Determines whether [is simple type] [the specified type]. | |
| /// </summary> | |
| /// <param name="type">The type to check.</param> | |
| /// <returns> | |
| /// <c>true</c> if [is simple type] [the specified type]; otherwise, <c>false</c>. | |
| /// </returns> | |
| private static bool IsSimpleType(this Type type) | |
| { | |
| return type.IsPrimitive || _writeTypes.Contains(type); | |
| } | |
| /// <summary> | |
| /// Converts the specified dynamic object to XML. | |
| /// </summary> | |
| /// <param name="dynamicObject">The dynamic object.</param> | |
| /// <returns>Returns an Xml representation of the dynamic object.</returns> | |
| public static XElement ConvertToXml(dynamic dynamicObject) | |
| { | |
| return ConvertToXml(dynamicObject, null); | |
| } | |
| /// <summary> | |
| /// Converts the specified dynamic object to XML. | |
| /// </summary> | |
| /// <param name="dynamicObject">The dynamic object.</param> | |
| /// <param name="element">The element name.</param> | |
| /// <returns>Returns an Xml representation of the dynamic object.</returns> | |
| public static XElement ConvertToXml(dynamic dynamicObject, string element) | |
| { | |
| if (string.IsNullOrWhiteSpace(element)) | |
| { | |
| element = "object"; | |
| } | |
| element = XmlConvert.EncodeName(element); | |
| var ret = new XElement(element); | |
| Dictionary<string, object> members = new Dictionary<string, object>(dynamicObject); | |
| var elements = from prop in members | |
| let name = XmlConvert.EncodeName(prop.Key) | |
| let val = prop.Value.GetType().IsArray ? "array" : prop.Value | |
| let value = prop.Value.GetType().IsArray ? GetArrayElement(prop.Key, (Array)prop.Value) : HandleSimpleType(prop, name, val) | |
| where value != null | |
| select value; | |
| ret.Add(elements); | |
| return ret; | |
| } | |
| private static XElement HandleSimpleType(KeyValuePair<string, object> prop, string name, object val) | |
| { | |
| return prop.Value.GetType().IsSimpleType() ? new XElement(name, val) : val.ToXml(name); | |
| } | |
| /// <summary> | |
| /// Generates an XML string from the dynamic object. | |
| /// </summary> | |
| /// <param name="dynamicObject">The dynamic object.</param> | |
| /// <returns>Returns an XML string.</returns> | |
| public static string ToXmlString(dynamic dynamicObject) | |
| { | |
| XElement xml = DynamicHelper.ConvertToXml(dynamicObject); | |
| return xml.ToString(); | |
| } | |
| /// <summary> | |
| /// Converts an anonymous type to an XElement. | |
| /// </summary> | |
| /// <param name="input">The input.</param> | |
| /// <returns>Returns the object as it's XML representation in an XElement.</returns> | |
| public static XElement ToXml(this object input) // NOSONAR: we want this method to be as general as possible | |
| { | |
| return input.ToXml(null!); | |
| } | |
| /// <summary> | |
| /// Converts an anonymous type to an XElement. | |
| /// </summary> | |
| /// <param name="input">The input.</param> | |
| /// <param name="element">The element name.</param> | |
| /// <returns>Returns the object as it's XML representation in an XElement.</returns> | |
| public static XElement ToXml(this object input, string element) // NOSONAR: we want this method to be as general as possible | |
| { | |
| if (input == null) | |
| { | |
| return null!; | |
| } | |
| if (string.IsNullOrWhiteSpace(element)) | |
| { | |
| element = "object"; | |
| } | |
| element = XmlConvert.EncodeName(element); | |
| var ret = new XElement(element); | |
| if (input != null) | |
| { | |
| var type = input.GetType(); | |
| var props = type.GetProperties(); | |
| var elements = from prop in props | |
| let name = XmlConvert.EncodeName(prop.Name) | |
| let val = prop.PropertyType.IsArray ? "array" : prop.GetValue(input, null) | |
| let value = prop.PropertyType.IsArray ? GetArrayElement(prop, (Array)prop.GetValue(input, null)!) : HandleSimpleProperty(prop, name, val) | |
| where value != null | |
| select value; | |
| ret.Add(elements); | |
| } | |
| return ret; | |
| } | |
| private static XElement HandleSimpleProperty(PropertyInfo prop, string name, object val) | |
| { | |
| return prop.PropertyType.IsSimpleType() ? new XElement(name, val) : val.ToXml(name); | |
| } | |
| /// <summary> | |
| /// Gets the array element. | |
| /// </summary> | |
| /// <param name="info">The property info.</param> | |
| /// <param name="input">The input object.</param> | |
| /// <returns>Returns an XElement with the array collection as child elements.</returns> | |
| private static XElement GetArrayElement(MemberInfo info, Array input) | |
| { | |
| return GetArrayElement(info.Name, input); | |
| } | |
| /// <summary> | |
| /// Gets the array element. | |
| /// </summary> | |
| /// <param name="propertyName">The property name.</param> | |
| /// <param name="input">The input object.</param> | |
| /// <returns>Returns an XElement with the array collection as child elements.</returns> | |
| private static XElement GetArrayElement(string propertyName, Array input) | |
| { | |
| var name = XmlConvert.EncodeName(propertyName); | |
| XElement rootElement = new XElement(name); | |
| var arrayCount = input.GetLength(0); | |
| for (int i = 0; i < arrayCount; i++) | |
| { | |
| var val = input.GetValue(i) ?? throw new ArgumentNullException(nameof(input)); | |
| XElement childElement = val.GetType().IsSimpleType() ? new XElement(name + "Child", val) : val.ToXml(); | |
| rootElement.Add(childElement); | |
| } | |
| return rootElement; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment