private object HandleListDerivative(XElement root, string propName, Type type) { Type type1 = type.IsGenericType ? type.GetGenericArguments()[0] : type.BaseType.GetGenericArguments()[0]; IList list1 = (IList)Activator.CreateInstance(type); IList <XElement> list2 = (IList <XElement>)Enumerable.ToList <XElement>(root.Descendants(XmlExtensions.AsNamespaced(type1.Name, this.Namespace))); string name = type1.Name; DeserializeAsAttribute attribute = ReflectionExtensions.GetAttribute <DeserializeAsAttribute>(type1); if (attribute != null) { name = attribute.Name; } if (!Enumerable.Any <XElement>((IEnumerable <XElement>)list2)) { XName name1 = XmlExtensions.AsNamespaced(name.ToLower(), this.Namespace); list2 = (IList <XElement>)Enumerable.ToList <XElement>(root.Descendants(name1)); } if (!Enumerable.Any <XElement>((IEnumerable <XElement>)list2)) { XName name1 = XmlExtensions.AsNamespaced(StringExtensions.ToCamelCase(name, this.Culture), this.Namespace); list2 = (IList <XElement>)Enumerable.ToList <XElement>(root.Descendants(name1)); } if (!Enumerable.Any <XElement>((IEnumerable <XElement>)list2)) { list2 = (IList <XElement>)Enumerable.ToList <XElement>(Enumerable.Where <XElement>(root.Descendants(), (Func <XElement, bool>)(e => StringExtensions.RemoveUnderscoresAndDashes(e.Name.LocalName) == name))); } if (!Enumerable.Any <XElement>((IEnumerable <XElement>)list2)) { XName lowerName = XmlExtensions.AsNamespaced(name.ToLower(), this.Namespace); list2 = (IList <XElement>)Enumerable.ToList <XElement>(Enumerable.Where <XElement>(root.Descendants(), (Func <XElement, bool>)(e => (XName)StringExtensions.RemoveUnderscoresAndDashes(e.Name.LocalName) == lowerName))); } this.PopulateListFromElements(type1, (IEnumerable <XElement>)list2, list1); if (!type.IsGenericType) { this.Map((object)list1, root.Element(XmlExtensions.AsNamespaced(propName, this.Namespace)) ?? root); } return((object)list1); }
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 { if (prop.GetCustomAttributes(typeof(PagedResultDataAttribute), false).Any()) { name = _pagedDataRootName; } 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); }
private object HandleListDerivative(XElement root, string propName, Type type) { //#if !NETSTANDARD1_6 Type t = type.IsGenericType ? type.GetGenericArguments()[0] : type.BaseType.GetGenericArguments()[0]; //#else // Type t = type.GetTypeInfo().IsGenericType // ? type.GenericTypeArguments[0] // : type.GetTypeInfo().BaseType.GenericTypeArguments[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 !NETSTANDARD1_6 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(); bool deserializeFromContentAttributeAlreadyUsed = false; foreach (var prop in props) { var type = prop.PropertyType.GetTypeInfo(); var typeIsPublic = type.IsPublic || type.IsNestedPublic; if (!typeIsPublic || !prop.CanWrite) { continue; } bool deserializeFromContent = false; bool isNameDefinedInAttribute = false; XName name = null; var attributes = prop.GetCustomAttributes(typeof(DeserializeAsAttribute), false); if (attributes.Any()) { DeserializeAsAttribute attribute = (DeserializeAsAttribute)attributes.First(); name = attribute.Name.AsNamespaced(Namespace); isNameDefinedInAttribute = !string.IsNullOrEmpty(name?.LocalName); deserializeFromContent = attribute.Content; if (deserializeFromContentAttributeAlreadyUsed && deserializeFromContent) { throw new ArgumentException("Class cannot have two properties marked with " + "SerializeAs(Content = true) attribute."); } deserializeFromContentAttributeAlreadyUsed |= deserializeFromContent; } if (name == null) { name = prop.Name.AsNamespaced(Namespace); } var value = GetValueFromXml(root, name, prop, isNameDefinedInAttribute); if (value == null) { // special case for text content node if (deserializeFromContent) { var textNode = root.Nodes().FirstOrDefault(n => n is XText); if (textNode != null) { value = ((XText)textNode).Value; prop.SetValue(x, value, null); } continue; } // special case for inline list items if (type.IsGenericType) { var genericType = type.GetGenericArguments()[0]; var first = GetElementByName(root, genericType.Name); var list = (IList)Activator.CreateInstance(type.AsType()); if (first != null && root != null) { var elements = root.Elements(first.Name); PopulateListFromElements(genericType, elements, list); } prop.SetValue(x, list, null); } continue; } if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>)) { // 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].GetTypeInfo(); } var asType = type.AsType(); if (asType == typeof(bool)) { var toConvert = value.ToString() .ToLower(); prop.SetValue(x, XmlConvert.ToBoolean(toConvert), null); } else if (type.IsPrimitive) { prop.SetValue(x, value.ChangeType(asType, Culture), null); } else if (type.IsEnum) { var converted = type.AsType().FindEnumValue(value.ToString(), Culture); prop.SetValue(x, converted, null); } else if (asType == typeof(Uri)) { var uri = new Uri(value.ToString(), UriKind.RelativeOrAbsolute); prop.SetValue(x, uri, null); } else if (asType == typeof(string)) { prop.SetValue(x, value, null); } else if (asType == typeof(DateTime)) { value = DateFormat.HasValue() ? DateTime.ParseExact(value.ToString(), DateFormat, Culture) : DateTime.Parse(value.ToString(), Culture); prop.SetValue(x, value, null); } else if (asType == typeof(DateTimeOffset)) { var toConvert = value.ToString(); if (string.IsNullOrEmpty(toConvert)) { continue; } DateTimeOffset deserialisedValue; try { deserialisedValue = XmlConvert.ToDateTimeOffset(toConvert); prop.SetValue(x, deserialisedValue, null); } catch (Exception) { if (TryGetFromString(toConvert, out var result, asType)) { prop.SetValue(x, result, null); } else { //fallback to parse deserialisedValue = DateTimeOffset.Parse(toConvert); prop.SetValue(x, deserialisedValue, null); } } }
protected virtual object Map(object x, XElement root) { Type objType = x.GetType(); PropertyInfo[] props = objType.GetTypeInfo().GetProperties(); foreach (PropertyInfo prop in props) { Type type = prop.PropertyType; //#if !NETSTANDARD1_6 bool typeIsPublic = type.IsPublic || type.IsNestedPublic; //#else // bool typeIsPublic = type.GetTypeInfo().IsPublic || type.GetTypeInfo().IsNestedPublic; //#endif if (!typeIsPublic || !prop.CanWrite) { continue; } XName name; //#if !NETSTANDARD1_6 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 !NETSTANDARD1_6 if (type.IsGenericType) //#else // if (type.GetTypeInfo().IsGenericType) //#endif { Type genericType = type.GenericTypeArguments[0]; XElement first = this.GetElementByName(root, genericType.Name); IList list = (IList)Activator.CreateInstance(type); if (first != 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 !NETSTANDARD1_6 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.GenericTypeArguments[0]; } if (type == typeof(bool)) { string toConvert = value.ToString() .ToLower(); prop.SetValue(x, XmlConvert.ToBoolean(toConvert), null); } //#if !NETSTANDARD1_6 else if (type.IsPrimitive) //#else // else if (type.GetTypeInfo().IsPrimitive) //#endif { prop.SetValue(x, value.ChangeType(type, this.Culture), null); } //#if !NETSTANDARD1_6 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 !NETSTANDARD1_6 else if (type.IsGenericType) //#else // else if (type.GetTypeInfo(). IsGenericType) //#endif { Type t = type.GenericTypeArguments[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); }