派生类C#的XML反序列化

时间:2016-03-02 15:54:50

标签: c# xml deserialization

我有下一个代码:

[XmlRoot(ElementName = "Container")]
public class Container {
    [XmlArray("Items", IsNullable = false)]
    [XmlArrayItem("Item")]
    public List<BaseItem> Items { get; set; } = new List<BaseItem>();
}


public class BaseItem {
    [XmlAttribute("SomeField")]
    public string SomeField {get;set;}
}


public class DerivedItem : BaseItem {
    [XmlAttribute("OtherField")]
    public string OtherField {get;set;}
}

如何反序列化:

<Container>
   <Items>
        <Item SomeField="Value"/>
        <Item SomeField="Value" OtherField="OtherValue"/>
   </Items>
</Container>

那么,Container对象中的Items字段可以包含上面XML的BaseItem和DerivedItem对象吗?

2 个答案:

答案 0 :(得分:0)

嗯,你不能,因为反序列化XmlSerializer时不确定何时使用BaseItem或DerivedItem。所以你不应该在这里使用继承。

现在您可能需要知道是否指定了OtherField。

幸运的是,这是XmlSerializer可以做的事情。为此,您需要向表示项目的类添加一个bool属性OtherFieldSpecified,它指示OtherField是否正确...指定。

你应该使用

// Define other methods and classes here
[XmlRoot(ElementName = "Container")]
public class Container {
    [XmlArray("Items", IsNullable = false)]
    [XmlArrayItem("Item")]
    public List<DerivedItem> Items { get; set; }

}

public class DerivedItem
{
    [XmlAttribute("SomeField")]
    public string SomeField {get;set;}

    [XmlAttribute("OtherField")]
    public string OtherField {get;set;}

    public bool OtherFieldSpecified {get;set;}
}

所以稍微调整工作linqPad scribble给了我这段代码:

void Main()
{

var xml = @"
<Container>
<Items>
        <Item SomeField=""Value""/>
        <Item SomeField=""Value"" OtherField=""OtherValue""/>
</Items>
</Container>
";

var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml));

    var ser = new XmlSerializer(typeof(Container));

    var container = (Container) ser.Deserialize(stream);

    container.Dump();
}

答案 1 :(得分:0)

我们可以从你开始不发布有效的XML吗?

元素是独一无二的。继承(派生类型)必须更改元素名称。这是XML标准,因为元素名称是XML Schema如何确定存在哪些元素。

你可以这样做,然后你可以添加多个XmlArrayItem条目 - 第二个重载采用所包含项的类型。