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));
            }
        }
Exemple #5
0
        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");
            }
        }