将一些XML(通过Stream)反序列化为父/子对象

时间:2010-08-04 16:33:12

标签: c# generics serialization xml-serialization

我有一个相当简单的DAL程序集,其中包含一个SalesEnquiry类,其中包含另一个List<T>类的Vehicle

我们将通过电子邮件接收XML文件,我想用它来填充SalesEnquiry类的实例,所以我正在尝试使用反序列化。

我已将XMLRoot / XMLElement / XMLIgnore属性添加到我认为合适的两个类中。但是,当我尝试反序列化时,将填充父SalesEnquiry对象,但没有子Vehicle对象。

我理解反序列化List<T>可能很棘手,但我不知道为什么,如何避免问题,或者即使这就是我为什么要挣扎的原因。

在调试时,我已经成功地序列化了一个Vehicle对象,所以我假设我正朝着正确的方向前进,但是当我对SalesEnquiry XML(包含一个或多个子车辆)进行反序列化时),List<Vehicle>未填充。

我哪里错了?

更新

在测试项目中,我序列化了包含两辆车的SalesEnquiry并保存到文件中。然后我将文件加载反序列化为另一个SalesEnquiry对象。它奏效了!

那有什么区别?车辆记录如下:

<?xml version="1.0" encoding="utf-8"?>
<enquiry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <enquiry_no>100001</enquiry_no>
  <vehicles>
    <Vehicle>
      <vehicle_type>Car</vehicle_type>
      <vehicle_make>Ford</vehicle_make>
      <vehicle_model>C-Max</vehicle_model>
...

需要注意的是,Vehicle有一个初始资本,而我的传入XML却没有。在我的Vehicle课程中,我给了课程一个[XmlRoot("vehicle")]属性,但是我会将其作为链接,但显然它没有。我认为这是有道理的,因为虽然Vehicle本身就是一个类,但它只是我SalesEnquiry里面List中的一个数组项。

在这种情况下,问题是 - 如何对Vehicle类进行注释,以便将传入的XML元素(<vehicle>)映射到我的列表项({{1} })? Vehicle(或[XmlArrayItem]就此问题而言)“对此声明类型无效”。

在这个示例中,我可以请求生成XML的人使用[XmlElement]而不是<Vehicle>,但可能会出现我没有这种自由的情况,所以我宁愿学习解决方案而不是应用解决方法。


结论

通过将[XmlArrayItem(“vehicle”,typeof(Vehicle))]添加到我的List的现有装饰中,XML现在可以完全反序列化。呼!

1 个答案:

答案 0 :(得分:1)

这是一组具有适当装饰的工作对象:

(注意:XmlAnyElement和XmlAnyAttribute是可选的。我习惯于提升实体的灵活性。)

[XmlType("enquiry")]
[XmlRoot("enquiry")]
public class Enquiry
{
    private List<Vehicle> vehicles = new List<Vehicle>();

    [XmlElement("enquiry_no")]
    public int EnquiryNumber { get; set; }

    [XmlArray("vehicles")]
    [XmlArrayItem("Vehicle", typeof(Vehicle))]
    public List<Vehicle> Vehicles
    {
        get { return this.vehicles; }
        set { this.vehicles = value ?? new List<Vehicle>(); }
    }

    [XmlAnyElement]
    public XmlElement[] AnyElements;
    [XmlAnyAttribute]
    public XmlAttribute[] AnyAttributes;
}

public class Vehicle
{
    [XmlElement("vehicle_type")]
    public string VehicleType { get; set; }
    [XmlElement("vehicle_make")]
    public string VehicleMake { get; set; }
    [XmlElement("vehicle_model")]
    public string VehicleModel { get; set; }
}