将单个 XML 堆栈反序列化为多个对象

Deserializing a single XML stack into multiple objects

我正在做一个 return 是单个 XML 块的项目,因此:

<root>
  <x_val />
  <x_val2 />
  <x_addr1 />
  <x_addr2 />
  <x_city />
  <x_state />
  <x_country />
  <x_zip />
</root>

在这个项目中,我可以多次调用return各种信息,但大部分都会在底部包含地址信息。

在编写我的 C# classes 时,我不希望在我创建的每个响应对象中为这些节点中的每一个创建属性。相反,我更愿意定义一个地址对象,这样使用:

[XmlRoot("root")]
[Serializable]
public class ReturnItem1
{
    [XmlElement("x_val")]
    public string FirstValue{ get; set; }

    [XmlElement("x_val2")]
    public string SecondValue{ get; set; }

    public Address AddressInfo { get; set; }

    public ReturnItem1()
    {
        AddressInfo = new Address();
    }
}

public class Address
{
    [XmlElement("x_addr1")]
    public string Address1 { get; set; }

    [XmlElement("x_addr2")]
    public string Address2 { get; set; }

    [XmlElement("x_city")]
    public string City { get; set; }

    [XmlElement("x_state")]
    public string State { get; set; }

    [XmlElement("x_country")]
    public string Country { get; set; }

    [XmlElement("x_zip")]
    public string PostalCode { get; set; }
}

反序列化时,我执行以下逻辑(响应类型为 XElement):

var serializer = new XmlSerializer(typeof(ReturnItem1));
var returnObject = (ReturnItem1)serializer.Deserialize(response.CreateReader());

FirstValue 和 SecondValue 的值填充在 returnObject 中,但 Address 中的属性始终为空。

我试过将 [XmlRoot("root)"] 属性添加到地址 class,但这没有用。在地址 [=34= 上设置 XmlElement 属性也没有用] 在 ReturnItem1 到 "root" 或任何其他节点名称。

有没有办法使用这种方法将单个 XML 节点反序列化为具有一个或多个子对象的对象?

尝试使用与 XML 元素匹配的私有成员和封装它们的 public 地址 属性。请参阅此示例:

https://msdn.microsoft.com/en-us/library/6exf3h2k%28v=vs.110%29.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-3

我已经使用 TAMTAM 的建议将 XML 反序列化为对象,如下所示:

[DataContract(Name="root", Namespace = "")]
public class ReturnItem1
{
    [DataMember(Name = "x_val", Order = 0)]
    public string FirstValue { get; set; }

    [DataMember(Name = "x_val2", Order = 1)]
    public string SecondValue { get; set; }

    [DataMember(Name = "x_addr1", Order = 2)]
    private string _address;

    [DataMember(Name = "x_addr2", Order = 3)]
    private string _address2;

    [DataMember(Name = "x_city", Order = 4)]
    private string _city;

    [DataMember(Name = "x_state", Order = 5)]
    private string _state;

    [DataMember(Name = "x_country", Order = 6)]
    private string _country;

    [DataMember(Name = "x_zip", Order = 7)]
    private string _postalCode;

    public Address AddressInfo { get; set; }

    [OnDeserialized()]
    void OnDeserialized(StreamingContext context)
    {
        AddressInfo = new Address
        {
            Address1 = _address,
            Address2 = _address2,
            PostalCode = _postalCode,
            City = _city,
            Country = _country,
            State = _state
        };
    }
}

我终于找到了一个我可以接受的解决方案。 ReturnItem1 扩展了包含 AdditionalAttributesToDeserialize 列表的基 class。然后在 ReturnItem1 的 OnDeserialized 方法中,我将 "AddressInfo" 添加到该列表。反序列化基础对象后,我遍历该列表,使用反射查找 属性 和 属性 的类型,程序为每个条目创建一个新的 DataContractSerializer 并反序列化 属性 在使用反射将 属性 的值设置为新反序列化的对象之前。这是一种蛮力方法,在将 属性 名称添加到 AdditionalPropertiesToDeserialize 列表时很容易使它变得笨拙,但它确实允许我在一个地方定义我的对象和属性并随意重用它们.