예제 #1
0
        public object Deserialize(XmlTextReader reader, Type type, object context)
        {
            //If the object has a type converter then just read the attribute string
            TypeConverter conv = TypeDescriptor.GetConverter(type);

            if (CanSerialize(conv))
            {
                string strValue = reader.ReadElementString();
                object value    = conv.ConvertFromInvariantString(strValue);
                return(value);
            }

            //Create an instance of the type
            Object obj = Activator.CreateInstance(type);

            //Use the IXmlSerializable implementation if needed
            IXmlSerializable serializableObject = obj as IXmlSerializable;

            if (serializableObject != null)
            {
                serializableObject.ReadXml(reader);
                return(obj);
            }

            //parse all the attributes as properties
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(type);
            bool hasChildren = !reader.IsEmptyElement;

            if (reader.MoveToFirstAttribute())
            {
                do
                {
                    PropertyDescriptor prop = properties[reader.Name];
                    if (prop == null)
                    {
                        throw new InvalidOperationException("the property " + reader.Name + " does not exist on the object " + type.Name);
                    }

                    reader.ReadAttributeValue();
                    TypeConverter converter = prop.Converter;
                    object        value     = converter.ConvertFromInvariantString(reader.Value);
                    prop.SetValue(obj, value);
                }while (reader.MoveToNextAttribute());
            }
            reader.Read();

            if (hasChildren)
            {
                //Parse the children as properties
                while (true)
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        //If the property is read-only and a list then add the children to the list members
                        PropertyDescriptor prop = properties[reader.Name];
                        if (prop == null)
                        {
                            throw new InvalidOperationException("the property " + reader.Name + " does not exist on the object " + type.Name);
                        }

                        if (prop.IsReadOnly)
                        {
                            IList list = prop.GetValue(obj) as IList;
                            if (list != null)
                            {
                                DefaultListSerializer serializer = new DefaultListSerializer();
                                serializer.Deserialize(reader, list.GetType(), list);
                            }
                        }
                        else
                        {
                            //parse the value and set the property
                            object value = ObjectSerializer.Deserialize(reader, prop.PropertyType, null);
                            prop.SetValue(obj, value);
                        }
                    }
                    // If end element then we are done parsing children.
                    else if (reader.NodeType == XmlNodeType.EndElement)
                    {
                        reader.Read(); //end element
                        break;
                    }
                    else if (reader.EOF)
                    {
                        break;  //end of document
                    }
                    // If we don't explicitly handle this kind of node then ignore it.
                    else
                    {
                        reader.Read();
                    }
                }
            }
            return(obj);
        }