private void Map(XElement root, object obj)
{
var objType = obj.GetType();
var props = from p in objType.GetProperties()
let indexAttribute = p.GetAttribute<SerializeAsAttribute>()
where p.CanRead && p.CanWrite
orderby indexAttribute == null ? int.MaxValue : indexAttribute.Index
select p;
var globalOptions = objType.GetAttribute<SerializeAsAttribute>();
foreach (var prop in props) {
var name = prop.Name;
var rawValue = prop.GetValue(obj, null);
if (rawValue == null) {
continue;
}
var value = GetSerializedValue(rawValue);
var propType = prop.PropertyType;
var useAttribute = false;
var settings = prop.GetAttribute<SerializeAsAttribute>();
if (settings != null) {
name = settings.Name.HasValue() ? settings.Name : name;
useAttribute = settings.Attribute;
}
var options = prop.GetAttribute<SerializeAsAttribute>();
if (options != null) {
name = options.TransformName(name);
}
else if (globalOptions != null) {
name = globalOptions.TransformName(name);
}
var nsName = name.AsNamespaced(Namespace);
var element = new XElement(nsName);
if (propType.IsPrimitive || propType.IsValueType || propType == typeof(string)) {
if (useAttribute) {
root.Add(new XAttribute(name, value));
continue;
}
element.Value = value;
}
else if (rawValue is IList) {
var itemTypeName = "";
foreach (var item in (IList)rawValue) {
if (itemTypeName == "") {
itemTypeName = item.GetType().Name;
}
var instance = new XElement(itemTypeName);
Map(instance, item);
element.Add(instance);
}
}
else {
Map(element, rawValue);
}
root.Add(element);
}
}