void WriteEntry(XElement elem, string name, Type type, object value)
{
if (value == null)
{
if (typeof(IEnumerable).IsAssignableFrom(type))
{
return;
}
var args = type.GetGenericArguments();
if (args.Length == 1 && args[0].IsValueType)
{
var nullableType = typeof(Nullable<>).MakeGenericType(args);
if (type == nullableType)
{
elem.Add(new XElement(name, new XAttribute(xsiNamespace + "nil", true), null));
return;
}
}
return;
}
if (typeof(XContainer).IsAssignableFrom(type))
{
var container = (XContainer) value;
if (skipWrappingRawXml)
{
elem.Add(XElement.Parse(container.ToString()));
}
else
{
elem.Add(new XElement(name, XElement.Parse(container.ToString())));
}
return;
}
if (type.IsValueType || type == typeof(string) || type == typeof(Uri) || type == typeof(char))
{
elem.Add(new XElement(name, value));
return;
}
if (typeof(IEnumerable).IsAssignableFrom(type))
{
var xe = new XElement(name);
if (type == typeof(byte[]))
{
var base64String = Convert.ToBase64String((byte[]) value);
xe.Value = base64String;
}
else
{
var baseType = typeof(object);
var interfaces = type.GetInterfaces();
if (type.IsInterface)
{
interfaces = interfaces.Union(new[]
{
type
}).ToArray();
}
//Get generic type from list: T for List<T>, KeyValuePair<T,K> for IDictionary<T,K>
foreach (var interfaceType in interfaces)
{
var arr = interfaceType.GetGenericArguments();
if (arr.Length != 1)
{
continue;
}
if (typeof(IEnumerable<>).MakeGenericType(arr[0]).IsAssignableFrom(type))
{
baseType = arr[0];
break;
}
}
foreach (var obj in (IEnumerable) value)
{
if (obj != null && obj.GetType().IsSimpleType())
{
WriteEntry(xe, obj.GetType().Name, obj.GetType(), obj);
}
else
{
WriteObject(xe, baseType.SerializationFriendlyName(), baseType, obj);
}
}
}
elem.Add(xe);
return;
}
WriteObject(elem, name, type, value);
}