Exemple #1
0
        /// <exception cref="XmlSerializationException">
        ///   The member contains a derived type which is not explicitly defined by an XmlTypeDefAttribute which is required by the
        ///   current serialization settings.
        /// </exception>
        private void WriteMember(
            XmlSerializableMember member, Object memberValue, Boolean asAttribute,
            IEnumerable <XmlItemDefAttribute> itemAttributeOverrides = null
            )
        {
            XmlItemDefAttributeCollection itemDefAttributes = new XmlItemDefAttributeCollection(member.MemberInfo.ItemDefAttributes);

            if (itemAttributeOverrides != null)
            {
                itemDefAttributes.AddRange(itemAttributeOverrides);
            }

            String nameToWrite;

            if (memberValue != null)
            {
                Type    objectType = memberValue.GetType();
                Boolean typeIsExplicitlyDefined;
                nameToWrite = member.MemberInfo.GetMemberNameByType(objectType, out typeIsExplicitlyDefined);
                if (!typeIsExplicitlyDefined && this.Settings.RequiresExplicitTypeDefinition)
                {
                    var ex = new XmlSerializationException("The member contains a derived type which is not explicitly defined by an XmlTypeDefAttribute which is required by the current serialization settings.");
                    ex.Data.Add("MemberInfo", member.MemberInfo);
                    ex.Data.Add("Derived Type", objectType);
                    throw ex;
                }
            }
            else
            {
                nameToWrite = member.MemberInfo.Name;
            }

            this.WriteNode(nameToWrite, memberValue, asAttribute, itemDefAttributes, member.MemberInfo.Comment);
        }
Exemple #2
0
        /// <exception cref="XmlSerializationException">
        ///   The type requires to implement <see cref="IXmlCustomSerialized" /> to be serialized as an attribute.
        /// </exception>
        void IXmlSerializerInternal.SubSerialize(
            XmlWriter xmlWriter, Object instance, String rootName, Boolean asAttribute,
            XmlItemDefAttributeCollection itemDefAttributes
            )
        {
            if (xmlWriter == null)
            {
                throw new ArgumentNullException();
            }
            if (instance == null)
            {
                throw new ArgumentNullException();
            }
            if (!this.TargetType.IsAssignableFrom(instance.GetType()))
            {
                throw new ArgumentException();
            }
            if (String.IsNullOrEmpty(rootName))
            {
                throw new ArgumentNullException();
            }
            if (asAttribute && !this.IsCustomSerialized)
            {
                var ex = new XmlSerializationException("The type requires to implement IXmlCustomSerialized to be serialized as an attribute.");
                ex.Data.Add("Type Name", this.TargetType.FullName);
                throw ex;
            }

            this.Serialize(xmlWriter, instance, new XmlSerializationProvider(this, xmlWriter, rootName, asAttribute, itemDefAttributes));
        }
Exemple #3
0
        /// <exception cref="XmlSerializationException">
        ///   An error occurred while setting the value of the field or property.
        /// </exception>
        public void SetValue(Object instance, Object value)
        {
            if (instance == null)
            {
                throw new ArgumentNullException();
            }
            Contract.Assert(this.fieldInfo != null || this.propertyInfo != null);

            if (this.fieldInfo != null)
            {
                try {
                    this.fieldInfo.SetValue(instance, value);
                } catch (Exception exception) {
                    var ex = new XmlSerializationException("The value of the field could not be set. See exception details for more information.", exception);
                    ex.Data.Add("Field Info", this.fieldInfo);
                    throw ex;
                }

                return;
            }

            try {
                this.propertyInfo.SetValue(instance, value, null);
            } catch (Exception exception) {
                var ex = new XmlSerializationException("The value of the property could not be set. See exception details for more information.", exception);
                ex.Data.Add("Property Info", this.propertyInfo);
                throw ex;
            }
        }
Exemple #4
0
        /// <exception cref="XmlSerializationException">
        ///   An error occurred while serializing the given <paramref name="instance" />.
        /// </exception>
        private void Serialize(XmlWriter xmlWriter, Object instance, XmlSerializationProvider provider)
        {
            if (xmlWriter == null)
            {
                throw new ArgumentNullException();
            }
            if (instance == null)
            {
                throw new ArgumentNullException();
            }
            if (provider == null)
            {
                throw new ArgumentNullException();
            }
            if (!this.TargetType.IsAssignableFrom(instance.GetType()))
            {
                throw new ArgumentException();
            }
            Contract.Requires <ArgumentException>(
                xmlWriter.WriteState == WriteState.Content ||
                xmlWriter.WriteState == WriteState.Element ||
                xmlWriter.WriteState == WriteState.Start
                );


            if (!this.IsCustomSerialized)
            {
                provider.WriteAll(instance);
            }
            else
            {
                try {
                    ((IXmlCustomSerialized)instance).Serialize(provider);
                } catch (Exception exception) {
                    var ex = new XmlSerializationException("An error occurred while serializing the type. See inner exception for more details.", exception);
                    ex.Data.Add("Type Name", this.TargetType.FullName);
                    throw ex;
                }
            }

            if (xmlWriter.WriteState != WriteState.Start && xmlWriter.WriteState != WriteState.Closed)
            {
                if (!this.isSubSerializer)
                {
                    xmlWriter.WriteEndDocument();
                }
                else
                {
                    xmlWriter.WriteEndElement();
                }
            }
        }
Exemple #5
0
        /// <exception cref="XmlSerializationException">
        ///   An error occurred while deserializing the type.
        /// </exception>
        private Object Deserialize(XmlReader xmlReader, XmlDeserializationProvider xmlDeserializationProvider)
        {
            if (xmlReader == null)
            {
                throw new ArgumentNullException();
            }
            if (xmlDeserializationProvider == null)
            {
                throw new ArgumentNullException();
            }

            Object instance;

            if (!this.IsCustomSerialized)
            {
                try {
                    instance = Activator.CreateInstance(this.TargetType);
                } catch (Exception exception) {
                    var ex = new XmlSerializationException("The parameterless contructor of the type threw an exception. See inner exception for more details.", exception);
                    ex.Data.Add("Type Name", this.TargetType.FullName);
                    throw ex;
                }

                xmlDeserializationProvider.ReadAll(instance);
            }
            else
            {
                try {
                    instance = Activator.CreateInstance(this.TargetType, xmlDeserializationProvider);
                } catch (Exception exception) {
                    var ex = new XmlSerializationException("An error occurred while deserializing the type by its custom deserialization constructor. See inner exception for more details.", exception);
                    ex.Data.Add("Type Name", this.TargetType.FullName);
                    throw ex;
                }
            }

            if (xmlReader.NodeType == XmlNodeType.EndElement)
            {
                xmlReader.ReadEndElement();
            }

            return(instance);
        }
Exemple #6
0
        /// <exception cref="XmlSerializationException">
        ///   The type requires to implement <see cref="IXmlCustomSerialized" /> to be deserialized as an attribute.
        /// </exception>
        Object IXmlSerializerInternal.SubDeserialize(
            XmlReader xmlReader, String rootName, Boolean asAttribute, XmlItemDefAttributeCollection itemDefAttributes
            )
        {
            if (xmlReader == null)
            {
                throw new ArgumentNullException();
            }
            if (String.IsNullOrEmpty(rootName))
            {
                throw new ArgumentNullException();
            }
            if (asAttribute && !this.IsCustomSerialized)
            {
                var ex = new XmlSerializationException("The type requires to implement IXmlCustomSerialized to be deserialized as an attribute.");
                ex.Data.Add("Type Name", this.TargetType.FullName);
                throw ex;
            }

            return(this.Deserialize(xmlReader, new XmlDeserializationProvider(this, xmlReader, rootName, asAttribute, itemDefAttributes)));
        }
Exemple #7
0
        /// <exception cref="XmlSerializationException">
        ///   An error occurred while getting the items of the field or property.
        /// </exception>
        public void SetListItems(Object instance, IEnumerable <Object> items)
        {
            if (instance == null)
            {
                throw new ArgumentNullException();
            }
            if (items == null)
            {
                throw new ArgumentNullException();
            }
            if (!this.MemberInfo.IsCollection)
            {
                throw new InvalidOperationException();
            }

            IList collection = (this.GetValue(instance) as IList);

            if (collection == null)
            {
                var ex = new XmlSerializationException("The member needs to implement IList to have its items being deserialized.");
                if (this.propertyInfo != null)
                {
                    ex.Data.Add("Field Info", this.propertyInfo);
                }
                else
                {
                    ex.Data.Add("Property Info", this.propertyInfo);
                }

                throw ex;
            }

            foreach (Object item in items)
            {
                collection.Add(item);
            }
        }
Exemple #8
0
        public void ReadToRoot(String customName = null)
        {
            Contract.Requires <InvalidOperationException>(
                this.XmlReader.NodeType == XmlNodeType.None || this.XmlReader.NodeType == XmlNodeType.Element
                );

            while (this.XmlReader.NodeType != XmlNodeType.Element &&
                   this.XmlReader.Read())
            {
            }

            String rootName = customName;

            if (rootName == null)
            {
                rootName = this.ElementName;
            }

            if (this.XmlReader.LocalName != rootName)
            {
                if (customName == null)
                {
                    var ex = new XmlSerializationException("Root element name does not match the name defined by the metadata.");
                    ex.Data.Add("Read Name", this.XmlReader.LocalName);
                    ex.Data.Add("Expected Name", rootName);
                    throw ex;
                }
                else
                {
                    var ex = new XmlSerializationException("Root element name does not match the name given by the customName parameter.");
                    ex.Data.Add("Read Name", this.XmlReader.LocalName);
                    ex.Data.Add("Expected Name", rootName);
                    throw ex;
                }
            }
        }
Exemple #9
0
        /// <exception cref="ArgumentException">
        ///   The given type implements the <see cref="IXmlCustomSerialized" /> interface but does not define a constructor accepting
        ///   <see cref="XmlDeserializationProvider" /> as parameter.
        /// </exception>
        private void ReflectTypeData(IEnumerable <Type> typesToCache = null)
        {
            if (this.TargetType == null)
            {
                throw new InvalidOperationException();
            }

            this.isCustomSerialized = (this.TargetType.GetInterface("IXmlCustomSerialized", false) != null);

            if (this.IsCustomSerialized)
            {
                if (this.TargetType.GetConstructor(new[] { typeof(XmlDeserializationProvider) }) == null)
                {
                    var ex = new XmlSerializationException("The type implements the IXmlCustomSerialized interface but does not define a constructor accepting XmlDeserializationProvider as parameter.");
                    ex.Data.Add("Type Name", this.TargetType.FullName);
                    throw ex;
                }
            }
            else if (!this.TargetType.IsValueType) // A value type will always provide a parameterless constructor.
            {
                if (this.Settings.AllowsDeserialization && this.TargetType.GetConstructor(new Type[] {}) == null)
                {
                    var ex = new XmlSerializationException("The type has to implement a parameterless constructor to be deserialized.");
                    ex.Data.Add("Type Name", this.TargetType.FullName);
                    throw ex;
                }
            }

            // The types where reflection data has to be cached (where sub serializers have to be created) for.
            List <Type> typesToCacheNew = new List <Type>(20);

            if (typesToCache != null)
            {
                foreach (Type typeToCache in typesToCache)
                {
                    typesToCacheNew.Add(typeToCache);
                }
            }

            // Reflect Members
            MemberInfo[] memberInfos = this.TargetType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
            this.serializableMembers = new XmlSerializableMemberCollection();

            foreach (MemberInfo memberInfo in memberInfos)
            {
                XmlSerializableMember member = XmlSerializableMember.Create(memberInfo, typesToCacheNew, this.Settings);

                if (member != null)
                {
                    this.serializableMembers.Add(member);
                }
            }
            // Sort the members by their OrderIndex value.
            this.serializableMembers.Sort();

            for (Int32 i = 0; i < typesToCacheNew.Count; i++)
            {
                Type typeToCache = typesToCacheNew[i];

                if (
                    typeToCache != this.TargetType && typeToCache != null && !this.subSerializers.ContainsKey(typeToCache) &&
                    !XmlSerializationProvider.IsNativelySerializable(typeToCache)
                    )
                {
                    try {
                        this.subSerializers.Add(typeToCache, new XmlSerializer <Object>(typeToCache, this.subSerializers, this.Settings));
                    } catch (Exception exception) {
                        var ex = new XmlSerializationException(
                            "The type is not serializable. See inner exception for more details.", exception);
                        ex.Data.Add("Type", typeToCache);
                        throw ex;
                    }
                }
            }
        }
Exemple #10
0
        /// <exception cref="ArgumentException">
        ///   <see cref="T" /> is no class or struct or is an abstract class.
        /// </exception>
        private void ValidateAndGetRootAttribute(
            XmlSerializationSettings settings, XmlRootAttribute rootAttributeOverride, out XmlRootAttribute rootAttribute
            )
        {
            Contract.Ensures(Contract.ValueAtReturn <XmlRootAttribute>(out rootAttribute) != null);

            if (!this.TargetType.IsClass && !this.TargetType.IsValueType)
            {
                throw new XmlSerializationException("Type argument T has to be either a class or struct type.");
            }

            if (this.TargetType.IsAbstract)
            {
                throw new XmlSerializationException("Type argument T can not be an abstract class.");
            }

            if (this.TargetType.IsSubclassOf(typeof(Enum)))
            {
                throw new XmlSerializationException("Type argument T can not be an enumeration.");
            }

            if (rootAttributeOverride != null)
            {
                rootAttribute = rootAttributeOverride;
            }
            else
            {
                // Reflect the root attribute.
                rootAttribute = null;
                foreach (Object attribute in this.TargetType.GetCustomAttributes(false))
                {
                    XmlRootAttribute foundAttribute = (attribute as XmlRootAttribute);

                    if (foundAttribute != null)
                    {
                        rootAttribute = foundAttribute;
                        break;
                    }
                }
            }

            if (rootAttribute == null)
            {
                if (!settings.RequiresExplicitXmlMetadataAttributes)
                {
                    rootAttribute = new XmlRootAttribute();
                }
                else
                {
                    var ex = new XmlSerializationException("The type is not serializable because it does not define an XmlRootAttribute.");
                    ex.Data.Add("Type Name", this.TargetType.FullName);
                    throw ex;
                }
            }

            // Get a name for the root attribute if necessary.
            if (this.rootAttribute.Name == null)
            {
                if (!XmlReader.IsName(this.TargetType.Name))
                {
                    var ex = new XmlSerializationException(
                        "The XmlRootAttribute does not define a custom name and the name of the class is not a valid name for an xml element.");
                    ex.Data.Add("Class Name", this.TargetType.Name);
                    throw ex;
                }

                this.rootAttribute.Name = this.TargetType.Name;
            }
            else
            {
                if (!XmlReader.IsName(this.rootAttribute.Name))
                {
                    var ex = new XmlSerializationException("The XmlRootAttribute does not define a valid name for an xml element.");
                    ex.Data.Add("Root Name", this.rootAttribute.Name);
                    throw ex;
                }
            }
        }
Exemple #11
0
        /// <exception cref="ArgumentException">
        ///   The given <paramref name="type" /> is not natively deserializable.
        /// </exception>
        /// <exception cref="XmlSerializationException">
        ///   A collection can not be deserialized as an attribute.
        /// </exception>
        private Object ReadNativeObject(Type type, Boolean asAttribute, XmlItemDefAttributeCollection itemDefAttributes)
        {
            // Check for null value.
            if (asAttribute)
            {
                if (this.XmlReader.Value == this.Settings.NullAttributeName)
                {
                    return(null);
                }
            }
            else
            {
                if (this.XmlReader.GetAttribute(this.Settings.NullAttributeName) != null)
                {
                    return(null);
                }
            }

            if (typeof(System.Collections.IList).IsAssignableFrom(type) || typeof(System.Collections.IDictionary).IsAssignableFrom(type))
            {
                if (asAttribute)
                {
                    throw new XmlSerializationException("A collection can not be deserialized as an attribute.");
                }

                Contract.Assert(this.XmlReader.NodeType == XmlNodeType.Element);

                Object  collection;
                Boolean isDictionary = typeof(System.Collections.IDictionary).IsAssignableFrom(type);
                if (type.IsClass)
                {
                    ConstructorInfo constructorInfo = type.GetConstructor(new Type[] {});
                    if (constructorInfo == null)
                    {
                        var ex = new XmlSerializationException("An empty constructor is required to deserialize the given IList.");
                        ex.Data.Add("Collection Type", type);
                        throw ex;
                    }

                    try {
                        collection = constructorInfo.Invoke(new Object[] {});
                    } catch (Exception exception) {
                        var ex = new XmlSerializationException("Parameterless constructor of deserializable collection threw exception. See inner exception for more details.", exception);
                        ex.Data.Add("Collection Type", type);
                        throw ex;
                    }
                }
                else
                {
                    // Value type constructor, will never throw exceptions.
                    collection = Activator.CreateInstance(type);
                }

                if (!this.XmlReader.IsEmptyElement)
                {
                    while (this.XmlReader.Read() && this.XmlReader.NodeType != XmlNodeType.EndElement)
                    {
                        if (this.XmlReader.NodeType != XmlNodeType.Element)
                        {
                            continue;
                        }

                        XmlItemDefAttribute attribute;
                        if (!itemDefAttributes.TryGetAttribute(this.XmlReader.LocalName, out attribute))
                        {
                            if (this.Settings.RequiresExplicitCollectionItemDefinition)
                            {
                                var ex = new XmlSerializationException("The collection-node in the XML-Data contains a sub-node with a name which is not explictly defined by an XmlItemDefAttribute which is required by the current serialization settings.");
                                ex.Data.Add("Collection Type", type);
                                ex.Data.Add("Node Name", this.XmlReader.LocalName);
                                throw ex;
                            }
                        }

                        if (!isDictionary)
                        {
                            ((System.Collections.IList)collection).Add(this.ReadElementContent(attribute.Type));
                        }
                        else
                        {
                            Object key   = null;
                            Object value = null;
                            Type[] genericArgumentTypes = type.GetGenericArguments();
                            while (this.XmlReader.Read() && this.XmlReader.NodeType != XmlNodeType.EndElement)
                            {
                                if (this.XmlReader.NodeType != XmlNodeType.Element)
                                {
                                    continue;
                                }

                                if (this.XmlReader.Name == "Key")
                                {
                                    key = this.ReadElementContent(genericArgumentTypes[0]);
                                }
                                else if (this.XmlReader.Name == "Value")
                                {
                                    value = this.ReadElementContent(genericArgumentTypes[1]);
                                }
                            }

                            if (this.XmlReader.NodeType == XmlNodeType.EndElement)
                            {
                                this.XmlReader.ReadEndElement();
                            }

                            try {
                                ((System.Collections.IDictionary)collection).Add(key, value);
                            } catch (Exception exception) {
                                var ex = new XmlSerializationException("Add method of IDictionary implementing collection threw exception. See inner exception for more details.", exception);
                                ex.Data.Add("Collection Type", type);
                                throw ex;
                            }
                        }
                    }

                    if (this.XmlReader.NodeType == XmlNodeType.EndElement)
                    {
                        this.XmlReader.ReadEndElement();
                    }
                }

                return(collection);
            }

            if (type.Name == "KeyValuePair`2" && type.Namespace == "System.Collections.Generic")
            {
                if (asAttribute)
                {
                    throw new XmlSerializationException("The native type KeyValuePair<,> is not deserializable as attribute.");
                }

                Object key   = null;
                Object value = null;
                Type[] genericArgumentTypes = type.GetGenericArguments();
                while (this.XmlReader.Read() && this.XmlReader.NodeType != XmlNodeType.EndElement)
                {
                    if (this.XmlReader.NodeType != XmlNodeType.Element)
                    {
                        continue;
                    }

                    if (this.XmlReader.Name == "Key")
                    {
                        key = this.ReadElementContent(genericArgumentTypes[0]);
                    }
                    else if (this.XmlReader.Name == "Value")
                    {
                        value = this.ReadElementContent(genericArgumentTypes[1]);
                    }
                }

                if (this.XmlReader.NodeType == XmlNodeType.EndElement)
                {
                    this.XmlReader.ReadEndElement();
                }

                return(Activator.CreateInstance(type, key, value));
            }

            String fullTextValue;

            if (!asAttribute)
            {
                fullTextValue = this.XmlReader.ReadElementString();
            }
            else
            {
                fullTextValue = this.XmlReader.Value;
            }

            try {
                if (type.IsEnum)
                {
                    return(Enum.Parse(type, fullTextValue));
                }

                switch (type.FullName)
                {
                case "System.String":
                    return(fullTextValue);

                case "System.Boolean":
                    return(Boolean.Parse(fullTextValue));

                case "System.Byte":
                    return(Byte.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.SByte":
                    return(SByte.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.Int16":
                    return(Int16.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.Int32":
                    return(Int32.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.Int64":
                    return(Int64.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.UInt16":
                    return(UInt16.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.UInt32":
                    return(UInt32.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.UInt64":
                    return(UInt64.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.Single":
                    return(Single.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.Double":
                    return(Double.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.Decimal":
                    return(Decimal.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.Char":
                    return(Char.Parse(fullTextValue));

                case "System.DateTime":
                    return(DateTime.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.DBNull":
                    return(DBNull.Value);

                case "System.Version":
                    return(new Version(fullTextValue));

                case "System.DateTimeOffset":
                    return(DateTimeOffset.Parse(fullTextValue, this.Settings.CultureInfo));

                case "System.Guid":
                    return(new Guid(fullTextValue));

                case "System.Drawing.Color":
                    return(System.Drawing.ColorTranslator.FromHtml(fullTextValue));

                case "System.Drawing.Point":
                    String[] pointData = fullTextValue.Split(',');
                    return(new System.Drawing.Point(Int32.Parse(pointData[0]), Int32.Parse(pointData[1])));

                case "System.Drawing.PointF":
                    String[] pointFData = fullTextValue.Split(',');
                    return(new System.Drawing.PointF(Single.Parse(pointFData[0]), Single.Parse(pointFData[1])));

                case "System.Drawing.Rectangle":
                    String[] rectangleData = fullTextValue.Split(',');
                    return(new System.Drawing.Rectangle(
                               Int32.Parse(rectangleData[0]), Int32.Parse(rectangleData[1]),
                               Int32.Parse(rectangleData[2]), Int32.Parse(rectangleData[3])
                               ));

                case "System.Drawing.RectangleF":
                    String[] rectangleFData = fullTextValue.Split(',');
                    return(new System.Drawing.RectangleF(
                               Single.Parse(rectangleFData[0]), Single.Parse(rectangleFData[1]),
                               Single.Parse(rectangleFData[2]), Single.Parse(rectangleFData[3])
                               ));

                /*
                 * case "System.Windows.Point":
                 * return System.Windows.Point.Parse(fullTextValue);
                 * case "System.Windows.Rect":
                 * return System.Windows.Rect.Parse(fullTextValue);
                 * case "System.Windows.Media.Color":
                 * System.Drawing.Color color = System.Drawing.ColorTranslator.FromHtml(fullTextValue);
                 * return System.Windows.Media.Color.FromArgb(color.A, color.R, color.G, color.B);
                 * case "System.Windows.Media.Matrix":
                 * return System.Windows.Media.Matrix.Parse(fullTextValue);
                 * case "System.Windows.Media.Media3D.Matrix3D":
                 * return System.Windows.Media.Media3D.Matrix3D.Parse(fullTextValue);*/

                case "Common.Percentage":
                    return(Percentage.Parse(fullTextValue, this.Settings.CultureInfo));

                case "Common.IO.Path":
                    return(new Path(fullTextValue));
                }
            } catch (Exception exception) {
                var ex = new XmlSerializationException("Parsing of value failed.", exception);
                ex.Data.Add("Type", type);
                ex.Data.Add("Value", fullTextValue);
                throw ex;
            }

            var excep = new ArgumentException("The given type is not natively deserializable.", "type");

            excep.Data.Add("Type", type);
            throw excep;
        }
Exemple #12
0
        /// <exception cref="ArgumentException">
        ///   The given <paramref name="type" /> is not natively serializable.
        /// </exception>
        /// <exception cref="XmlSerializationException">
        ///   A type which implements <see cref="IEnumerable" /> can not be serialized as an attribute.
        /// </exception>
        private void WriteNativeObject(
            String nodeName, Type type, Object obj, Boolean asAttribute, XmlItemDefAttributeCollection itemDefAttributes
            )
        {
            if (nodeName == null)
            {
                throw new ArgumentNullException();
            }

            if (!asAttribute)
            {
                this.XmlWriter.WriteStartElement(nodeName);
            }
            else
            {
                this.XmlWriter.WriteStartAttribute(nodeName);
            }

            if (obj == null)
            {
                if (asAttribute)
                {
                    this.XmlWriter.WriteValue(this.Settings.NullAttributeName);
                }
                else
                {
                    this.XmlWriter.WriteAttributeString(this.Settings.NullAttributeName, true.ToString(this.Settings.CultureInfo));
                }
            }
            else if (type.FullName != "System.String" && typeof(IEnumerable).IsAssignableFrom(type))
            {
                if (asAttribute)
                {
                    throw new XmlSerializationException("A type which implements IEnumerable can not be serialized as an attribute.");
                }

                foreach (Object item in (IEnumerable)obj)
                {
                    Type   itemType = item.GetType();
                    String itemName;
                    XmlItemDefAttribute itemDefAttribute;

                    if (itemDefAttributes != null && itemDefAttributes.TryGetAttribute(itemType, out itemDefAttribute))
                    {
                        itemName = itemDefAttribute.Name;
                    }
                    else
                    {
                        if (this.Settings.RequiresExplicitCollectionItemDefinition)
                        {
                            var ex = new XmlSerializationException("A collection contains an item which is not explicitly defined by an XmlItemDefAttribute which is required by the current serialization settings.");
                            ex.Data.Add("Collection Type", type);
                            ex.Data.Add("Item Type", itemType);
                            throw ex;
                        }

                        itemName = itemType.FullName;
                        // Mask nested class' full name if required.
                        itemName = itemName.Replace('+', XmlSerializationProviderBase.NestedClassNameMaskCharacter);
                    }

                    this.WriteElement(itemName, item);
                }
            }
            else if (type.Name == "KeyValuePair`2" && type.Namespace == "System.Collections.Generic")
            {
                if (asAttribute)
                {
                    throw new XmlSerializationException("The native type KeyValuePair<,> is not serializable as an attribute.");
                }

                Object key   = type.GetProperty("Key").GetValue(obj, null);
                Object value = type.GetProperty("Value").GetValue(obj, null);
                this.WriteElement("Key", key);
                this.WriteElement("Value", value);
            }
            else if (type.IsEnum)
            {
                this.XmlWriter.WriteString(obj.ToString());
            }
            else
            {
                switch (type.FullName)
                {
                case "System.Drawing.Color":
                    this.XmlWriter.WriteString(System.Drawing.ColorTranslator.ToHtml((System.Drawing.Color)obj));
                    break;

                /*case "System.Windows.Media.Color":
                 * System.Windows.Media.Color mediaColor = (System.Windows.Media.Color)obj;
                 * Color color = Color.FromArgb(mediaColor.A, mediaColor.R, mediaColor.G, mediaColor.B);
                 * this.XmlWriter.WriteString(System.Drawing.ColorTranslator.ToHtml(color));
                 * break;*/

                case "System.Boolean":
                case "System.Byte":
                case "System.SByte":
                case "System.Int16":
                case "System.Int32":
                case "System.Int64":
                case "System.UInt16":
                case "System.UInt32":
                case "System.UInt64":
                case "System.Single":
                case "System.Double":
                case "System.Decimal":
                case "System.Char":
                case "System.String":
                case "System.DateTime":
                case "System.DBNull":
                    this.XmlWriter.WriteString(((IConvertible)obj).ToString(this.Settings.CultureInfo));
                    break;

                case "System.DateTimeOffset":
                    this.XmlWriter.WriteString(((System.DateTimeOffset)obj).ToString(this.Settings.CultureInfo));
                    break;

                /*
                 * case "System.Windows.Point":
                 * this.XmlWriter.WriteString(((System.Windows.Point)obj).ToString(this.Settings.CultureInfo));
                 * break;
                 * case "System.Windows.Rect":
                 * this.XmlWriter.WriteString(((System.Windows.Rect)obj).ToString(this.Settings.CultureInfo));
                 * break;
                 * case "System.Windows.Media.Matrix":
                 * this.XmlWriter.WriteString(((System.Windows.Media.Matrix)obj).ToString(this.Settings.CultureInfo));
                 * break;
                 * case "System.Windows.Media.Media3D.Matrix3D":
                 * this.XmlWriter.WriteString(((System.Windows.Media.Media3D.Matrix3D)obj).ToString(this.Settings.CultureInfo));
                 * break;*/
                case "Common.Percentage":
                    this.XmlWriter.WriteString(((Common.Percentage)obj).ToString(this.Settings.CultureInfo));
                    break;

                case "System.Drawing.Point":
                case "System.Drawing.PointF":
                case "System.Drawing.Rectangle":
                case "System.Drawing.RectangleF":
                case "System.Object":
                case "System.Version":
                case "System.Guid":
                case "Common.IO.Path":
                    this.XmlWriter.WriteString(obj.ToString());
                    break;

                default:
                    throw new ArgumentException("The given type is not natively serializable.", "type");
                }
            }

            if (!asAttribute)
            {
                this.XmlWriter.WriteEndElement();
            }
            else
            {
                this.XmlWriter.WriteEndAttribute();
            }
        }