示例#1
0
        internal XmlMemberInfo(
            String name, Type type, Int32 orderIndex, String comment, Boolean isAttribute, Boolean isStatic, Boolean isCollection,
            Type collectionItemType, XmlItemDefAttributeCollection itemDefAttributes, XmlTypeDefAttributeCollection typeDefAttributes
            )
        {
            if (name == null)
            {
                throw new ArgumentNullException();
            }
            if (type == null)
            {
                throw new ArgumentNullException();
            }
            if (itemDefAttributes == null)
            {
                throw new ArgumentNullException();
            }
            if (typeDefAttributes == null)
            {
                throw new ArgumentNullException();
            }
            if (orderIndex < -1)
            {
                throw new ArgumentOutOfRangeException();
            }

            this.name               = name;
            this.type               = type;
            this.orderIndex         = orderIndex;
            this.comment            = comment;
            this.isAttribute        = isAttribute;
            this.isStatic           = isStatic;
            this.isCollection       = isCollection;
            this.collectionItemType = collectionItemType;
            this.itemDefAttributes  = itemDefAttributes;
            this.typeDefAttributes  = typeDefAttributes;
        }
示例#2
0
        /// <exception cref="ArgumentException">
        ///   The reflected data are invalid.
        /// </exception>
        public static XmlSerializableMember Create(
            MemberInfo memberInfo, ICollection <Type> typesToCache, XmlSerializationSettings settings
            )
        {
            if (memberInfo == null)
            {
                throw new ArgumentNullException();
            }
            if (typesToCache == null)
            {
                throw new ArgumentNullException();
            }

            FieldInfo    fieldInfo    = (memberInfo as FieldInfo);
            PropertyInfo propertyInfo = (memberInfo as PropertyInfo);

            if (fieldInfo == null && propertyInfo == null)
            {
                return(null);
            }

            XmlSerializableMember serializableMember = new XmlSerializableMember(fieldInfo, propertyInfo);
            Type memberType;

            if (fieldInfo != null)
            {
                memberType = fieldInfo.FieldType;
            }
            else
            {
                memberType = propertyInfo.PropertyType;
            }

            // This check includes IList, ICollection, IEnumerable<T>, IList<T>, ICollection<T>.
            Type    collectionItemType = null;
            Boolean isCollection       = (memberType != typeof(String) && typeof(IEnumerable).IsAssignableFrom(memberType));
            Boolean isDictionary       = (typeof(IDictionary).IsAssignableFrom(memberType) || typeof(IDictionary <,>).IsAssignableFrom(memberType));

            if (isCollection)
            {
                if (memberType.IsGenericType)
                {
                    if (!isDictionary)
                    {
                        collectionItemType = memberType.GetGenericArguments()[0];
                    }
                    else
                    {
                        Type[] genericArgumentTypes = memberType.GetGenericArguments();
                        // TODO: There may be a better approach for this.
                        collectionItemType = Type.GetType(String.Format(
                                                              "System.Collections.Generic.KeyValuePair`2[[{0}],[{1}]]",
                                                              genericArgumentTypes[0].AssemblyQualifiedName, genericArgumentTypes[1].AssemblyQualifiedName
                                                              ));
                    }
                }
                else
                {
                    if (!isDictionary)
                    {
                        collectionItemType = typeof(Object);
                    }
                    else
                    {
                        collectionItemType = typeof(KeyValuePair <Object, Object>);
                    }
                }
            }

            Boolean isSerializable = false;
            String  memberName     = null;
            Int32   orderIndex     = 0;
            String  comment        = null;
            Boolean isAttribute    = false;
            XmlItemDefAttributeCollection itemDefAttributes = new XmlItemDefAttributeCollection();
            XmlTypeDefAttributeCollection typeDefAttributes = new XmlTypeDefAttributeCollection();

            if (!settings.RequiresExplicitXmlMetadataAttributes)
            {
                // With this settings, any field or property is serializable by default.
                memberName     = memberInfo.Name;
                isSerializable = true;
            }

            foreach (Attribute attribute in memberInfo.GetCustomAttributes(true))
            {
                if (attribute is XmlNodeAttribute)
                {
                    XmlNodeAttribute nodeAttribute = (XmlNodeAttribute)attribute;

                    if (nodeAttribute.Name == null)
                    {
                        memberName = memberInfo.Name;
                    }
                    else
                    {
                        memberName = nodeAttribute.Name;
                    }

                    if (nodeAttribute.OrderIndex == -1 && settings.RequiresExplicitOrder)
                    {
                        var ex = new ArgumentException("The XmlNodeAttribute on the member does not define an explicit order index as required by the current serialization settings.");
                        ex.Data.Add("Member Info", memberInfo);
                        throw ex;
                    }
                    comment     = nodeAttribute.Comment;
                    orderIndex  = nodeAttribute.OrderIndex;
                    isAttribute = nodeAttribute.IsAttribute;

                    isSerializable = true;

                    continue;
                }

                if (attribute is XmlNodeTypeDefAttribute)
                {
                    XmlNodeTypeDefAttribute typeDefAttribute = (XmlNodeTypeDefAttribute)attribute;
                    if (memberType == typeDefAttribute.Type)
                    {
                        var ex = new ArgumentException("XmlNodeTypeDefAttribute can not be of the same type as the member.");
                        ex.Data.Add("Member Info", memberInfo);
                        throw ex;
                    }
                    if (!memberType.IsAssignableFrom(typeDefAttribute.Type))
                    {
                        var ex = new ArgumentException("XmlNodeTypeDefAttribute defined with a type which is not castable to the member's type.");
                        ex.Data.Add("Member Info", memberInfo);
                        throw ex;
                    }

                    typeDefAttributes.Add(typeDefAttribute);
                }

                if (attribute is XmlItemDefAttribute)
                {
                    if (!isCollection)
                    {
                        var ex = new ArgumentException("XmlItemDefAttribute defined for a member of a type that does not implement the IEnumerable or IEnumerable<T> interface.");
                        ex.Data.Add("Member Info", memberInfo);
                        throw ex;
                    }

                    XmlItemDefAttribute itemDefAttribute = (XmlItemDefAttribute)attribute;

                    // Check if the type defined by the XmlItemDefAttribute is derived or equal to the collection's item type.
                    if (!collectionItemType.IsAssignableFrom(itemDefAttribute.Type))
                    {
                        var ex = new ArgumentException("The type given by the XmlItemDefAttribute is not assignable to the item type of the collection.");
                        ex.Data.Add("Member Info", memberInfo);
                        throw ex;
                    }

                    // Check if we have an item attribute for this type already.
                    if (itemDefAttributes.Contains(itemDefAttribute.Type))
                    {
                        var ex = new ArgumentException("Only one XmlItemDefAttribute is allowed for the same item type.");
                        ex.Data.Add("Item Type", itemDefAttribute.Type);
                        ex.Data.Add("Member Info", memberInfo);
                        throw ex;
                    }

                    itemDefAttributes.Add(itemDefAttribute);
                    typesToCache.Add(itemDefAttribute.Type);
                }
            }

            if (!isSerializable)
            {
                return(null);
            }

            if (settings.RequiresExplicitCollectionItemDefinition && isCollection && !itemDefAttributes.ContainsType(collectionItemType))
            {
                var ex = new ArgumentException("The collection member does not define an explicit XmlItemDefAttribute for its type as required by the current serialization settings.");
                ex.Data.Add("Member Info", memberInfo);
                ex.Data.Add("Item Type", collectionItemType);
                throw ex;
            }

            Boolean isStatic;

            if (fieldInfo != null)
            {
                isStatic = fieldInfo.IsStatic;
            }
            else
            {
                // We need at least one accessor to check whether the property is static etc.
                MethodInfo[] accessors = propertyInfo.GetAccessors(true);
                if (accessors.Length == 0)
                {
                    var ex = new ArgumentException("A XML-Serializable property requires at least one accessor.");
                    ex.Data.Add("Property Info", serializableMember.MemberInfo);
                    throw ex;
                }

                MethodInfo accessor = accessors[0];
                if (accessor.IsAbstract)
                {
                    var ex = new ArgumentException("A XML-Serializable property can not be abstract.");
                    ex.Data.Add("Property Info", serializableMember.MemberInfo);
                    throw ex;
                }

                isStatic = accessor.IsStatic;
            }

            // If any field or property should be serializable, we may not include static members.
            if (isStatic && !settings.RequiresExplicitXmlMetadataAttributes)
            {
                return(null);
            }

            serializableMember.memberInfo = new XmlMemberInfo(
                memberName, memberType, orderIndex, comment, isAttribute, isStatic, isCollection, collectionItemType,
                itemDefAttributes, typeDefAttributes
                );

            if (collectionItemType != null)
            {
                typesToCache.Add(collectionItemType);
            }
            typesToCache.Add(memberType);
            return(serializableMember);
        }