protected override object GetValueFromXml(XElement root, XName name, PropertyInfo prop) { bool isAttribute = false; //Check for the DeserializeAs attribute on the property DeserializeAsAttribute options = prop.GetAttribute <DeserializeAsAttribute>(); if (options != null) { name = options.Name ?? name; isAttribute = options.Attribute; } if (isAttribute) { XAttribute attributeVal = GetAttributeByName(root, name); if (attributeVal != null) { return(attributeVal.Value); } } return(base.GetValueFromXml(root, name, prop)); }
private object HandleListDerivative(XElement root, string propName, Type type) { #if !WINDOWS_UWP Type t = type.IsGenericType ? type.GetGenericArguments()[0] : type.BaseType.GetGenericArguments()[0]; #else Type t = type.GetTypeInfo().IsGenericType ? type.GetGenericArguments()[0] : type.GetTypeInfo().BaseType.GetGenericArguments()[0]; #endif IList list = (IList)Activator.CreateInstance(type); IList <XElement> elements = root.Descendants(t.Name.AsNamespaced(this.Namespace)) .ToList(); string name = t.Name; DeserializeAsAttribute attribute = t.GetAttribute <DeserializeAsAttribute>(); if (attribute != null) { name = attribute.Name; } if (!elements.Any()) { XName lowerName = name.ToLower().AsNamespaced(this.Namespace); elements = root.Descendants(lowerName).ToList(); } if (!elements.Any()) { XName camelName = name.ToCamelCase(this.Culture).AsNamespaced(this.Namespace); elements = root.Descendants(camelName).ToList(); } if (!elements.Any()) { elements = root.Descendants() .Where(e => e.Name.LocalName.RemoveUnderscoresAndDashes() == name) .ToList(); } if (!elements.Any()) { XName lowerName = name.ToLower().AsNamespaced(this.Namespace); elements = root.Descendants() .Where(e => e.Name.LocalName.RemoveUnderscoresAndDashes() == lowerName) .ToList(); } this.PopulateListFromElements(t, elements, list); // get properties too, not just list items // only if this isn't a generic type #if !WINDOWS_UWP if (!type.IsGenericType) #else if (!type.GetTypeInfo().IsGenericType) #endif { this.Map(list, root.Element(propName.AsNamespaced(this.Namespace)) ?? root); // when using RootElement, the heirarchy is different } return(list); }
protected virtual object Map(object x, XElement root) { Type objType = x.GetType(); PropertyInfo[] props = objType.GetProperties(); foreach (PropertyInfo prop in props) { Type type = prop.PropertyType; #if !WINDOWS_UWP bool typeIsPublic = type.IsPublic || type.IsNestedPublic; #else bool typeIsPublic = type.GetTypeInfo().IsPublic || type.GetTypeInfo().IsNestedPublic; #endif if (!typeIsPublic || !prop.CanWrite) { continue; } XName name; #if !WINDOWS_UWP object[] attributes = prop.GetCustomAttributes(typeof(DeserializeAsAttribute), false); if (attributes.Length > 0) #else IEnumerable <Attribute> attributes = prop.GetCustomAttributes(typeof(DeserializeAsAttribute), false); if (attributes.Count() > 0) #endif { DeserializeAsAttribute attribute = (DeserializeAsAttribute)attributes.First(); name = attribute.Name.AsNamespaced(this.Namespace); } else { name = prop.Name.AsNamespaced(this.Namespace); } object value = this.GetValueFromXml(root, name, prop); if (value == null) { // special case for inline list items #if !WINDOWS_UWP if (type.IsGenericType) #else if (type.GetTypeInfo().IsGenericType) #endif { Type genericType = type.GetGenericArguments()[0]; XElement first = this.GetElementByName(root, genericType.Name); IList list = (IList)Activator.CreateInstance(type); if (first != null && root != null) { IEnumerable <XElement> elements = root.Elements(first.Name); this.PopulateListFromElements(genericType, elements, list); } prop.SetValue(x, list, null); } continue; } // check for nullable and extract underlying type #if !WINDOWS_UWP if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>)) #else if (type.GetTypeInfo().IsGenericType&& type.GetGenericTypeDefinition() == typeof(Nullable <>)) #endif { // if the value is empty, set the property to null... if (string.IsNullOrEmpty(value.ToString())) { prop.SetValue(x, null, null); continue; } type = type.GetGenericArguments()[0]; } if (type == typeof(bool)) { string toConvert = value.ToString() .ToLower(); prop.SetValue(x, XmlConvert.ToBoolean(toConvert), null); } #if !WINDOWS_UWP else if (type.IsPrimitive) #else else if (type.GetTypeInfo().IsPrimitive) #endif { prop.SetValue(x, value.ChangeType(type, this.Culture), null); } #if !WINDOWS_UWP else if (type.IsEnum) #else else if (type.GetTypeInfo().IsEnum) #endif { object converted = type.FindEnumValue(value.ToString(), this.Culture); prop.SetValue(x, converted, null); } else if (type == typeof(Uri)) { Uri uri = new Uri(value.ToString(), UriKind.RelativeOrAbsolute); prop.SetValue(x, uri, null); } else if (type == typeof(string)) { prop.SetValue(x, value, null); } else if (type == typeof(DateTime)) { value = this.DateFormat.HasValue() ? DateTime.ParseExact(value.ToString(), this.DateFormat, this.Culture) : DateTime.Parse(value.ToString(), this.Culture); prop.SetValue(x, value, null); } else if (type == typeof(DateTimeOffset)) { string toConvert = value.ToString(); if (!string.IsNullOrEmpty(toConvert)) { DateTimeOffset deserialisedValue; try { deserialisedValue = XmlConvert.ToDateTimeOffset(toConvert); prop.SetValue(x, deserialisedValue, null); } catch (Exception) { object result; if (TryGetFromString(toConvert, out result, type)) { prop.SetValue(x, result, null); } else { //fallback to parse deserialisedValue = DateTimeOffset.Parse(toConvert); prop.SetValue(x, deserialisedValue, null); } } } } else if (type == typeof(decimal)) { value = decimal.Parse(value.ToString(), this.Culture); prop.SetValue(x, value, null); } else if (type == typeof(Guid)) { string raw = value.ToString(); value = string.IsNullOrEmpty(raw) ? Guid.Empty : new Guid(value.ToString()); prop.SetValue(x, value, null); } else if (type == typeof(TimeSpan)) { TimeSpan timeSpan = XmlConvert.ToTimeSpan(value.ToString()); prop.SetValue(x, timeSpan, null); } #if !WINDOWS_UWP else if (type.IsGenericType) #else else if (type.GetTypeInfo().IsGenericType) #endif { Type t = type.GetGenericArguments()[0]; IList list = (IList)Activator.CreateInstance(type); XElement container = this.GetElementByName(root, prop.Name.AsNamespaced(this.Namespace)); if (container.HasElements) { XElement first = container.Elements().FirstOrDefault(); if (first != null) { IEnumerable <XElement> elements = container.Elements(first.Name); this.PopulateListFromElements(t, elements, list); } } prop.SetValue(x, list, null); } else if (type.IsSubclassOfRawGeneric(typeof(List <>))) { // handles classes that derive from List<T> // e.g. a collection that also has attributes object list = this.HandleListDerivative(root, prop.Name, type); prop.SetValue(x, list, null); } else { //fallback to type converters if possible object result; if (TryGetFromString(value.ToString(), out result, type)) { prop.SetValue(x, result, null); } else { // nested property classes if (root != null) { XElement element = this.GetElementByName(root, name); if (element != null) { object item = this.CreateAndMap(type, element); prop.SetValue(x, item, null); } } } } } return(x); }
private object Map(object target, IDictionary <string, object> data) { Type objType = target.GetType(); List <PropertyInfo> props = objType.GetProperties() .Where(p => p.CanWrite) .ToList(); foreach (PropertyInfo prop in props) { string name; Type type = prop.PropertyType; #if !WINDOWS_UWP object[] attributes = prop.GetCustomAttributes(typeof(DeserializeAsAttribute), false); if (attributes.Length > 0) #else IEnumerable <Attribute> attributes = prop.GetCustomAttributes(typeof(DeserializeAsAttribute), false); if (attributes.Count() > 0) #endif { DeserializeAsAttribute attribute = (DeserializeAsAttribute)attributes.First(); name = attribute.Name; } else { name = prop.Name; } string[] parts = name.Split('.'); IDictionary <string, object> currentData = data; object value = null; for (int i = 0; i < parts.Length; ++i) { string actualName = parts[i].GetNameVariants(this.Culture) .FirstOrDefault(currentData.ContainsKey); if (actualName == null) { break; } if (i == parts.Length - 1) { value = currentData[actualName]; } else { currentData = (IDictionary <string, object>)currentData[actualName]; } } if (value != null) { prop.SetValue(target, this.ConvertValue(type, value), null); } } return(target); }