Can I serialize Anonymous Types as xml? Can I serialize Anonymous Types as xml? xml xml

Can I serialize Anonymous Types as xml?


Something like this should get you started...

class Program{    static void Main(string[] args)    {        var me = new        {            Hello = "World",            Other = new            {                My = "Object",                V = 1,                B = (byte)2            }        };        var x = me.ToXml();    }}public static class Tools{    private static readonly Type[] WriteTypes = new[] {        typeof(string), typeof(DateTime), typeof(Enum),         typeof(decimal), typeof(Guid),    };    public static bool IsSimpleType(this Type type)    {        return type.IsPrimitive || WriteTypes.Contains(type);    }    public static XElement ToXml(this object input)    {        return input.ToXml(null);    }    public static XElement ToXml(this object input, string element)    {        if (input == null)            return null;        if (string.IsNullOrEmpty(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.GetValue(input, null)                           let value = prop.PropertyType.IsSimpleType()                                ? new XElement(name, val)                                : val.ToXml(name)                           where value != null                           select value;            ret.Add(elements);        }        return ret;    }}

... resulting xml ...

<object>  <Hello>World</Hello>  <Other>    <My>Object</My>    <V>1</V>    <B>2</B>  </Other></object>


It can't be accomplished using XmlSerializer nor DataContractSerializer. It can be done by a manually written code, as demonstrated below (I can't comment as to whether the code is comprehensive enough to handle all types - but it's a very good start).


Thank you, excellent work @Matthew and @Martin.

I have made a couple of modification to accomodate Nullables and Enums. Also I have changed it so that array elements are named according to the name of the property + index.

Here is the code if anyone is interested

public static class ObjectExtensions {    #region Private Fields    private static readonly Type[] WriteTypes = new[] {        typeof(string), typeof(DateTime), typeof(Enum),         typeof(decimal), typeof(Guid),    };    #endregion Private Fields    #region .ToXml    /// <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) {        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) {        return _ToXml(input, element);    }    private static XElement _ToXml(object input, string element, int? arrayIndex = null, string arrayName = null) {        if (input == null)            return null;        if (String.IsNullOrEmpty(element)) {            string name = input.GetType().Name;            element = name.Contains("AnonymousType")                 ? "Object"                 : arrayIndex != null                    ? arrayName + "_" + arrayIndex                    : name;        }        element = XmlConvert.EncodeName(element);        var ret = new XElement(element);        if (input != null) {            var type = input.GetType();            var props = type.GetProperties();            var elements = props.Select(p => {                var pType = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType;                var name = XmlConvert.EncodeName(p.Name);                var val = pType.IsArray ? "array" : p.GetValue(input, null);                var value = pType.IsArray                     ? GetArrayElement(p, (Array)p.GetValue(input, null))                    : pType.IsSimpleType() || pType.IsEnum                         ? new XElement(name, val)                         : val.ToXml(name);                return value;            })            .Where(v=>v !=null);            ret.Add(elements);        }        return ret;    }    #region helpers    /// <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(PropertyInfo info, Array input) {        var name = XmlConvert.EncodeName(info.Name);        XElement rootElement = new XElement(name);        var arrayCount = input == null ? 0 : input.GetLength(0);        for (int i = 0; i < arrayCount; i++) {            var val = input.GetValue(i);            XElement childElement = val.GetType().IsSimpleType() ? new XElement(name + "_" + i, val) : _ToXml(val, null, i, name);            rootElement.Add(childElement);        }        return rootElement;    }    #region .IsSimpleType    public static bool IsSimpleType(this Type type) {        return type.IsPrimitive || WriteTypes.Contains(type);    }    #endregion .IsSimpleType    #endregion helpers    #endregion .ToXml}