反序列化为子类问题

时间:2015-05-23 06:53:36

标签: c# xml xsd deserialization xmlserializer

我一直在尝试将一些XML反序列化为一个类,它是另一个类的子类。当我尝试反序列化到基类时它工作。但是,当类被反序列化为任何子类时,它将失败。

我想知道为什么会这样。这是OOP设计违规还是我错过了什么。感谢

以下是代码:

基类:Shape.cs

namespace Shape
{
    using System.Xml.Serialization;


    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(IsNullable = false)]
    [KnownType(typeof(Rectangle))]
    [KnownType(typeof(Square))]

    public partial class Shape
    {

        private string widthField;

        private string heightField;

        private string colorField;

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public string Width
        {
            get
            {
                return this.widthField;
            }
            set
            {
                this.widthField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public string Height
        {
            get
            {
                return this.heightField;
            }
            set
            {
                this.heightField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public string Color
        {
            get
            {
                return this.colorField;
            }
            set
            {
                this.colorField = value;
            }
        }
    }

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class NewDataSet
    {

        private Shape[] itemsField;

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("Shape")]
        public Shape[] Items
        {
            get
            {
                return this.itemsField;
            }
            set
            {
                this.itemsField = value;
            }
        }
    }
}

子类#1:Rectangle.cs

namespace Shape
{
    public class Rectangle : Shape
    {
    }
}

子类#2:Square.cs

namespace Shape
{
    public class Square : Shape
    {
    }
}

尝试将XML反序列化为Rectangle(Subclass#1)

的类
    string xmlSample = "<?xml version=\"1.0\" ?><Shape xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"><Width>2</Width><Height>5</Height><Color>Red</Color></Shape>";
    //Shape.Shape shape = Utilities.ByteArrayToObject<Shape.Shape>(Utilities.XmlStringToBytes(xmlSample)); <-- Works OK
    Shape.Rectangle rect = Utilities.ByteArrayToObject<Shape.Rectangle>(Utilities.XmlStringToBytes(xmlSample));  //<-- Will fail

XSD形状架构:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
  <xs:element name="Shape">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Width" type="xs:string" minOccurs="0" />
        <xs:element name="Height" type="xs:string" minOccurs="0" />
        <xs:element name="Color" type="xs:string" minOccurs="0" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="Shape" />
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

3 个答案:

答案 0 :(得分:2)

见下面的代码。我发现了一些问题。 XML只能有一个根节点,但您有一个Shape []数组作为根。所以我添加到你的xml NewDataSet中。类中对象的名称与xml中的标记不匹配。所以我在类中添加了XmlElement。我还将XmlAttribute更改为XmlElement。 XmlAttribute在XML中具有相同的符号。你在尖括号之间的Xml中有TEXT。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Data;


namespace Shape
{
    class Program
    {
        static void Main(string[] args)
        {
            string xmlSample = "<?xml version=\"1.0\"?><NewDataSet xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><Shape xsi:type=\"Rectangle\"><Width>2</Width><Height>5</Height><Color>Red</Color></Shape></NewDataSet>";
            StringReader reader = new StringReader(xmlSample);

            XmlSerializer xs = new XmlSerializer(typeof(NewDataSet));
            NewDataSet ds = (NewDataSet)xs.Deserialize(reader);

        }

    }
    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [XmlInclude(typeof(Rectangle))]
    [XmlInclude(typeof(Square))]
    [XmlRoot("Shape")]
    public partial class Shape
    {
        private string widthField;
        private string heightField;
        private string colorField;

        /// <remarks/>
        [XmlElement("Width")]
        public string Width
        {
            get
            {
                return this.widthField;
            }
            set
            {
                this.widthField = value;
            }
        }

        /// <remarks/>
        [XmlElement("Height")]
        public string Height
        {
            get
            {
                return this.heightField;
            }
            set
            {
                this.heightField = value;
            }
        }

        /// <remarks/>
        [XmlElement("Color")]
        public string Color
        {
            get
            {
                return this.colorField;
            }
            set
            {
                this.colorField = value;
            }
        }
    }
    [XmlRoot("Rectangle")]
    public class Rectangle : Shape
    {
    }
    [XmlRoot("Square")]
    public class Square : Shape
    {
    }

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    //[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    [XmlRoot("NewDataSet")]
    public partial class NewDataSet
    {

        private Shape[] itemsField;

        /// <remarks/>
        [XmlElement("Shape")]
        public Shape[] Items
        {
            get
            {
                return this.itemsField;
            }
            set
            {
                this.itemsField = value;
            }
        }
    }


}
​

答案 1 :(得分:0)

转换为基类型被认为是C#中的安全隐式类型转换。但反之则不然。

答案 2 :(得分:0)

管理以找到解决方案。解决方法是在子类中添加[XmlRoot(“Shape”)]来修复问题。

示例:

[XmlRoot("Shape")]
public class Rectangle : Shape
{ .. }

和'Square'类

也是一样的