private object HandleListDerivative(XElement root, string propName, Type type) { Type realType = type.IsGenericType ? type.GetGenericArguments()[0] : type.BaseType.GetGenericArguments()[0]; IList list = (IList)Activator.CreateInstance(type); string name = realType.Name; SerializeInfoAttribute attribute = realType.GetCustomAttribute <SerializeInfoAttribute>(); if (attribute != null) { name = attribute.Name; } IEnumerable <XElement> elements = FindDescendants(root, name); PopulateListFromElements(realType, elements, list); if (!type.IsGenericType) { Map(list, root.Element(propName) ?? root); } return(list); }
private object Map(object x, XElement root) { Type objType = x.GetType(); PropertyInfo[] props = objType.GetProperties(); foreach (PropertyInfo prop in props) { Type type = prop.PropertyType; bool typeIsPublic = type.IsPublic || type.IsNestedPublic; if (!typeIsPublic || !prop.CanWrite) { continue; } XName name = prop.Name; bool isAttr = false; SerializeInfoAttribute attribute = prop.GetCustomAttribute <SerializeInfoAttribute>(false); if (attribute != null) { name = attribute.Name; isAttr = attribute.IsAttribute; } string value = GetValueFromXml(root, name, isAttr); //We have 2 case for lists. The first one: // //<list> // <item></item> // <item></item> //</list> // //In this case we use the property's real name to find the container and map the items from children //Second one: // //<item></item> //<item></item> // //In this case we use the generic type's real name and use the root to find the children if (value == null) { if (type.IsGenericType) { Type genericType = type.GetGenericArguments()[0]; string realName = genericType.Name; SerializeInfoAttribute attr = genericType.GetCustomAttribute <SerializeInfoAttribute>(); if (attr != null) { realName = attr.Name; } XElement first = GetElementByName(root, realName); IList list = (IList)Activator.CreateInstance(type); if (first != null && root != null) { IEnumerable <XElement> elements = root.Elements(first.Name); PopulateListFromElements(genericType, elements, list); } prop.SetValue(x, list, null); } continue; } if (TryParseSimpleValue(value, type, out object parsedValue)) { prop.SetValue(x, parsedValue, null); continue; } //If it wasn't a supported primitive type, objVal is null here if (type.IsGenericType) { if (type.GetGenericTypeDefinition() == typeof(Nullable <>)) { prop.SetValue(x, null, null); continue; } IList list = (IList)Activator.CreateInstance(type); XElement container = GetElementByName(root, name); if (container.HasElements) { XElement first = container.Elements().FirstOrDefault(); if (first != null) { Type t = type.GetGenericArguments()[0]; IEnumerable <XElement> elements = container.Elements(first.Name); PopulateListFromElements(t, elements, list); } } prop.SetValue(x, list, null); } else if (typeof(List <>).IsAssignableFrom(type)) { object objVal = HandleListDerivative(root, prop.Name, type); if (objVal != null) { prop.SetValue(x, objVal, null); } } else { // nested property classes if (root == null) { continue; } XElement element = GetElementByName(root, name); if (element == null) { continue; } object objVal = CreateAndMap(type, element); if (objVal != null) { prop.SetValue(x, objVal, null); } } } return(x); }