Десериализация одного стека XML в несколько объектов

Я работаю над проектом, который возвращает один блок XML как таковой:

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

В этом проекте я могу сделать несколько вызовов, которые возвращают различную информацию, но большинство из них будут содержать информацию об адресе внизу.

При написании своих классов C# я бы предпочел не создавать свойства для каждого из этих узлов в каждом отдельном объекте ответа, который я создаю. Вместо этого я бы предпочел определить один объект Address для использования как таковой:

[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 всегда имеют значение null.

Я попытался добавить атрибут [XmlRoot("root)"] в класс Address, но это не сработало. Также не было задано для атрибута XmlElement свойства Address в ReturnItem1 значение «root» или любое другое имя узла.

Есть ли способ использовать этот подход для десериализации одного XML-узла в объект с одним или несколькими подобъектами?


person Andrew K. Setter    schedule 24.03.2015    source источник


Ответы (2)



Мне удалось десериализовать XML в объект, используя предложение TAMTAM, следующим образом:

[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. Затем в методе OnDeserialized объекта ReturnItem1 я добавляю «AddressInfo» в этот список. После десериализации базового объекта я перебираю этот список, используя Reflection, чтобы найти свойство и тип свойства, и для каждой записи программа создает новый DataContractSerializer и десериализует свойство перед использованием Reflection, чтобы установить значение свойства в новое значение. десериализованный объект. Это немного грубый подход, и он склонен к тому, чтобы жирно перебирать имя свойства при добавлении его в список AdditionalPropertiesToDeserialize, но он позволяет мне определять мои объекты и атрибуты в одном месте и повторно использовать их по желанию.

person Andrew K. Setter    schedule 25.03.2015