using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml;
using System.Xml.Linq;
///
/// Extension methods for the dynamic object.
///
public static class DynamicHelper
{
///
/// Defines the simple types that is directly writeable to XML.
///
private static readonly Type[] _writeTypes = new[] { typeof(string), typeof(DateTime), typeof(Enum), typeof(decimal), typeof(Guid) };
///
/// Determines whether [is simple type] [the specified type].
///
/// The type to check.
///
/// true if [is simple type] [the specified type]; otherwise, false.
///
public static bool IsSimpleType(this Type type)
{
return type.IsPrimitive || _writeTypes.Contains(type);
}
///
/// Converts the specified dynamic object to XML.
///
/// The dynamic object.
/// Returns an Xml representation of the dynamic object.
public static XElement ConvertToXml(dynamic dynamicObject)
{
return ConvertToXml(dynamicObject, null);
}
///
/// Converts the specified dynamic object to XML.
///
/// The dynamic object.
/// /// The element name.
/// Returns an Xml representation of the dynamic object.
public static XElement ConvertToXml(dynamic dynamicObject, string element)
{
if (String.IsNullOrWhiteSpace(element))
{
element = "object";
}
element = XmlConvert.EncodeName(element);
var ret = new XElement(element);
Dictionary members = new Dictionary(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) : (prop.Value.GetType().IsSimpleType() ? new XElement(name, val) : val.ToXml(name))
where value != null
select value;
ret.Add(elements);
return ret;
}
///
/// Generates an XML string from the dynamic object.
///
/// The dynamic object.
/// Returns an XML string.
public static string ToXmlString(dynamic dynamicObject)
{
XElement xml = DynamicHelper.ConvertToXml(dynamicObject);
return xml.ToString();
}
///
/// Converts an anonymous type to an XElement.
///
/// The input.
/// Returns the object as it's XML representation in an XElement.
public static XElement ToXml(this object input)
{
return input.ToXml(null);
}
///
/// Converts an anonymous type to an XElement.
///
/// The input.
/// The element name.
/// Returns the object as it's XML representation in an XElement.
public static XElement ToXml(this object input, string element)
{
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)) : (prop.PropertyType.IsSimpleType() ? new XElement(name, val) : val.ToXml(name))
where value != null
select value;
ret.Add(elements);
}
return ret;
}
///
/// Parses the specified XML string to a dynamic.
///
/// The XML string.
/// A dynamic object.
public static dynamic ParseDynamic(this string xmlString)
{
throw new NotImplementedException();
}
///
/// Gets the array element.
///
/// The property info.
/// The input object.
/// Returns an XElement with the array collection as child elements.
private static XElement GetArrayElement(PropertyInfo info, Array input)
{
return GetArrayElement(info.Name, input);
}
///
/// Gets the array element.
///
/// The property name.
/// The input object.
/// Returns an XElement with the array collection as child elements.
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);
XElement childElement = val.GetType().IsSimpleType() ? new XElement(name + "Child", val) : val.ToXml();
rootElement.Add(childElement);
}
return rootElement;
}
}