object GetPropertyValue(Type type, XmlNode n)
{
if ((n.ChildNodes.Count == 1) && n.ChildNodes[0] is XmlCharacterData)
{
var text = n.ChildNodes[0].InnerText;
var args = type.GetGenericArguments();
if (args.Length == 1 && args[0].IsValueType)
{
if (args[0].GetGenericArguments().Any())
{
return GetPropertyValue(args[0], n);
}
var nullableType = typeof(Nullable<>).MakeGenericType(args);
if (type == nullableType)
{
if (text.Trim().ToLower() == "null" || string.IsNullOrWhiteSpace(text))
{
return null;
}
return GetPropertyValue(args[0], n);
}
}
if (type == typeof(string))
{
return text;
}
if (type == typeof(bool))
{
return XmlConvert.ToBoolean(text);
}
if (type == typeof(byte))
{
return XmlConvert.ToByte(text);
}
if (type == typeof(char))
{
return XmlConvert.ToChar(text);
}
if (type == typeof(DateTime))
{
return XmlConvert.ToDateTime(text, XmlDateTimeSerializationMode.RoundtripKind);
}
if (type == typeof(DateTimeOffset))
{
return XmlConvert.ToDateTimeOffset(text);
}
if (type == typeof(decimal))
{
return XmlConvert.ToDecimal(text);
}
if (type == typeof(double))
{
return XmlConvert.ToDouble(text);
}
if (type == typeof(Guid))
{
return XmlConvert.ToGuid(text);
}
if (type == typeof(short))
{
return XmlConvert.ToInt16(text);
}
if (type == typeof(int))
{
return XmlConvert.ToInt32(text);
}
if (type == typeof(long))
{
return XmlConvert.ToInt64(text);
}
if (type == typeof(sbyte))
{
return XmlConvert.ToSByte(text);
}
if (type == typeof(float))
{
return XmlConvert.ToSingle(text);
}
if (type == typeof(TimeSpan))
{
return XmlConvert.ToTimeSpan(text);
}
if (type == typeof(ushort))
{
return XmlConvert.ToUInt16(text);
}
if (type == typeof(uint))
{
return XmlConvert.ToUInt32(text);
}
if (type == typeof(ulong))
{
return XmlConvert.ToUInt64(text);
}
if (type.IsEnum)
{
return Enum.Parse(type, text);
}
if (type == typeof(byte[]))
{
return Convert.FromBase64String(text);
}
if (type == typeof(Uri))
{
return new Uri(text);
}
if (!typeof(IEnumerable).IsAssignableFrom(type))
{
if (n.ChildNodes[0] is XmlWhitespace)
{
return Activator.CreateInstance(type);
}
throw new Exception($"Type not supported by the serializer: {type.AssemblyQualifiedName}");
}
}
if (typeof(XContainer).IsAssignableFrom(type))
{
var reader = new StringReader(skipWrappingRawXml ? n.OuterXml : n.InnerXml);
if (type == typeof(XDocument))
{
return XDocument.Load(reader);
}
return XElement.Load(reader);
}
//Handle dictionaries
if (typeof(IDictionary).IsAssignableFrom(type))
{
var result = Activator.CreateInstance(type) as IDictionary;
var keyType = typeof(object);
var valueType = typeof(object);
foreach (var interfaceType in type.GetInterfaces())
{
var args = interfaceType.GetGenericArguments();
if (args.Length != 2)
{
continue;
}
if (typeof(IDictionary<,>).MakeGenericType(args[0], args[1]).IsAssignableFrom(type))
{
keyType = args[0];
valueType = args[1];
break;
}
}
foreach (XmlNode xn in n.ChildNodes) // go over KeyValuePairs
{
object key = null;
object value = null;
foreach (XmlNode node in xn.ChildNodes)
{
if (node.Name == "Key")
{
key = GetObjectOfTypeFromNode(keyType, node);
}
if (node.Name == "Value")
{
value = GetObjectOfTypeFromNode(valueType, node);
}
}
if (result != null && key != null)
{
result[key] = value;
}
}
return result;
}
if (typeof(IEnumerable).IsAssignableFrom(type) && type != typeof(string))
{
var isArray = type.IsArray;
var isISet = false;
if (type.IsGenericType && type.GetGenericArguments().Length == 1)
{
var setType = typeof(ISet<>).MakeGenericType(type.GetGenericArguments());
isISet = setType.IsAssignableFrom(type);
}
var typeToCreate = type;
if (isArray)
{
typeToCreate = cache.typesToCreateForArrays[type];
}
Type typeToCreateForEnumerables;
if (cache.typesToCreateForEnumerables.TryGetValue(type, out typeToCreateForEnumerables)) //handle IEnumerable<Something>
{
typeToCreate = typeToCreateForEnumerables;
}
if (typeof(IList).IsAssignableFrom(typeToCreate))
{
var list = Activator.CreateInstance(typeToCreate) as IList;
if (list != null)
{
foreach (XmlNode xn in n.ChildNodes)
{
if (xn.NodeType == XmlNodeType.Whitespace)
{
continue;
}
var m = Process(xn, list);
list.Add(m);
}
if (isArray)
{
return typeToCreate.GetMethod("ToArray").Invoke(list, null);
}
if (isISet)
{
return Activator.CreateInstance(type, typeToCreate.GetMethod("ToArray").Invoke(list, null));
}
}
return list;
}
}
if (n.ChildNodes.Count == 0)
{
if (type == typeof(string))
{
return string.Empty;
}
return null;
}
return GetObjectOfTypeFromNode(type, n);
}