private void ReadProperty(XmlElement element, Type type, BXmlPropertyAttribute propertyAttribute, string attributePrefix, PropertyInfo property, IReader reader) { bool found = false; Type targetType = GetReadTargetType(propertyAttribute, property); BXmlElementAttribute elementAttribute1 = targetType.GetCustomAttribute <BXmlElementAttribute>(); BXmlSelectAttribute selectAttribute = targetType.GetCustomAttribute <BXmlSelectAttribute>(); if ((!propertyAttribute.ChildElement || elementAttribute1 == null) && string.IsNullOrEmpty(propertyAttribute.Name)) { throw new InvalidOperationException($"The value of the property {type.FullName}.{property.Name} must have the name specified in the {nameof(BXmlPropertyAttribute)}"); } if ((propertyAttribute.ChildElement || propertyAttribute.Collection) && (elementAttribute1 == null && selectAttribute == null)) { throw new InvalidOperationException($"The type of the property {type.FullName}.{property.Name} must have either {nameof(BXmlElementAttribute)} or {nameof(BXmlSelectAttribute)}"); } if (propertyAttribute.ChildElement) { found = ReadChildElementProperty(element, propertyAttribute, property, reader, targetType, elementAttribute1, selectAttribute); } else if (propertyAttribute.Collection) { found = ReadCollectionProperty(element, propertyAttribute, property, reader, targetType, elementAttribute1, selectAttribute); } else { found = ReadAttributeProperty(element, type, propertyAttribute, attributePrefix, property, reader); } if (!found && !propertyAttribute.Optional) { throw new InvalidOperationException($"The value of the property {type.FullName}.{property.Name} is not found but the property is not optional"); } }
private bool ReadCollectionProperty(XmlElement element, BXmlPropertyAttribute propertyAttribute, PropertyInfo property, IReader reader, Type targetType, BXmlElementAttribute elementAttribute1, BXmlSelectAttribute selectAttribute) { object collection = ReadCollectionProperty_InitializeCollection(property, targetType, reader); MethodInfo method = collection.GetType().GetMethod("Add", new Type[] { targetType }); if (method == null) { throw new InvalidOperationException($"The type of the property {property.DeclaringType.FullName}.{property.Name} has no Add({targetType.FullName}) method"); } var collectionElement = FindChildElement(element, propertyAttribute.Name); if (collectionElement == null) { return(false); } object[] parameters = new object[] { null }; Func <XmlElement, object> deserializer; if (elementAttribute1 != null) { deserializer = e => Deserialize(e, targetType); } else { deserializer = e => Deserialize(e, selectAttribute.Options); } foreach (XmlNode node in collectionElement.ChildNodes) { if (node is not XmlElement childElement) { continue; } parameters[0] = deserializer(childElement); method.Invoke(collection, parameters); } if (reader.CanSet(property)) { if (property.PropertyType.IsArray) { collection = collection.GetType().GetMethod("ToArray", new Type[] { }).Invoke(collection, Array.Empty <object>()); } reader.Set(property, collection); } return(true); }
private bool ReadChildElementProperty_NotFlatten(XmlElement element, PropertyInfo property, IReader reader, Type targetType, BXmlElementAttribute elementAttribute1, BXmlSelectAttribute selectAttribute, string elementToSearch) { bool found = false; var childElement = FindChildElement(element, elementToSearch); if (childElement != null) { object propertyValue; if (elementAttribute1 != null) { propertyValue = Deserialize(childElement, targetType); } else { propertyValue = Deserialize(childElement, selectAttribute.Options); } reader.Set(property, propertyValue); found = true; } return(found); }
private bool ReadChildElementProperty(XmlElement element, BXmlPropertyAttribute propertyAttribute, PropertyInfo property, IReader reader, Type targetType, BXmlElementAttribute elementAttribute1, BXmlSelectAttribute selectAttribute) { string elementToSearch = null; if (elementAttribute1 == null && string.IsNullOrEmpty(propertyAttribute.Name)) { throw new InvalidOperationException($"The value of the property {property.DeclaringType.FullName}.{property.Name} must have the name specified in the {nameof(BXmlPropertyAttribute)}"); } elementToSearch = propertyAttribute.Name ?? elementAttribute1?.Name; if (!propertyAttribute.FlattenChild) { return(ReadChildElementProperty_NotFlatten(element, property, reader, targetType, elementAttribute1, selectAttribute, elementToSearch)); } else { return(ReadChildElementProperty_Flatten(element, property, reader, targetType, elementToSearch)); } }
private void ReadProperty(XmlElement element, Type type, string propertyName, Type propertyType, BXmlPropertyAttribute propertyAttribute, string attributePrefix, Action <object> setProperty, Func <object> getProperty = null) { bool found = false; Type targetType = null; if (propertyAttribute.Collection) { foreach (Type iface in propertyType.GetInterfaces()) { if (iface.IsGenericType && iface.GetGenericTypeDefinition() == typeof(IEnumerable <>)) { targetType = iface.GetGenericArguments()[0]; break; } } if (targetType == null) { throw new InvalidOperationException($"The type of the value {type.FullName}.{propertyName} must implement IEnumerable interface"); } } else { targetType = Nullable.GetUnderlyingType(propertyType) ?? propertyType; } BXmlElementAttribute elementAttribute1 = targetType.GetCustomAttribute <BXmlElementAttribute>(); BXmlSelectAttribute selectAttribute = targetType.GetCustomAttribute <BXmlSelectAttribute>(); if ((!propertyAttribute.ChildElement || elementAttribute1 == null) && string.IsNullOrEmpty(propertyAttribute.Name)) { throw new InvalidOperationException($"The value of the property {type.FullName}.{propertyName} must have the name specified in the {nameof(BXmlPropertyAttribute)}"); } if ((propertyAttribute.ChildElement || propertyAttribute.Collection) && (elementAttribute1 == null && selectAttribute == null)) { throw new InvalidOperationException($"The type of the property {type.FullName}.{propertyName} must have either {nameof(BXmlElementAttribute)} or {nameof(BXmlSelectAttribute)}"); } if (propertyAttribute.ChildElement) { string elementToSearch = null; if (elementAttribute1 == null && string.IsNullOrEmpty(propertyAttribute.Name)) { throw new InvalidOperationException($"The value of the property {type.FullName}.{propertyName} must have the name specified in the {nameof(BXmlPropertyAttribute)}"); } elementToSearch = propertyAttribute.Name ?? elementAttribute1?.Name; if (!propertyAttribute.FlattenChild) { var childElement = FindChildElement(element, elementToSearch); if (childElement != null) { object propertyValue; if (elementAttribute1 != null) { propertyValue = Deserialize(childElement, targetType); } else { propertyValue = Deserialize(childElement, selectAttribute.Options); } setProperty(propertyValue); found = true; } } else { string prefix = $"{elementToSearch}-"; bool any = false; for (int i = 0; !any && i < element.Attributes.Count; i++) { if (element.Attributes[i].Name.StartsWith(prefix)) { any = true; } } if (any) { object propertyValue = Deserialize(element, targetType, elementToSearch); setProperty(propertyValue); found = true; } } } else if (propertyAttribute.Collection) { object collection = null; if (setProperty != null) { if (propertyType.IsArray) { collection = Activator.CreateInstance(typeof(List <>).MakeGenericType(targetType)); } else { collection = Activator.CreateInstance(propertyType); } } else { if (getProperty != null) { collection = getProperty(); } if (collection == null) { throw new InvalidOperationException($"The value of the property {type.FullName}.{propertyName} has no set accessor and is not initialized by default"); } } MethodInfo method = collection.GetType().GetMethod("Add", new Type[] { targetType }); if (method == null) { throw new InvalidOperationException($"The type of the property {type.FullName}.{propertyName} has no Add({targetType.FullName}) method"); } var collectionElement = FindChildElement(element, propertyAttribute.Name); if (collectionElement != null) { object[] parameters = new object[] { null }; foreach (XmlNode node in collectionElement.ChildNodes) { if (node is XmlElement childElement) { if (elementAttribute1 != null) { parameters[0] = Deserialize(childElement, targetType); } else { parameters[0] = Deserialize(childElement, selectAttribute.Options); } method.Invoke(collection, parameters); } } if (setProperty != null) { if (propertyType.IsArray) { collection = collection.GetType().GetMethod("ToArray", new Type[] { }).Invoke(collection, Array.Empty <object>()); } setProperty(collection); } found = true; } } else { object propertyValue = ReadAttribute(type, element, propertyName, propertyType, propertyAttribute, attributePrefix); if (propertyValue != null) { setProperty(propertyValue); found = true; } } if (!found && !propertyAttribute.Optional) { throw new InvalidOperationException($"The value of the property {type.FullName}.{propertyName} is not found but the property is not optional"); } }