예제 #1
0
        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));
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }