簡體   English   中英

使用XmlSerializer以可擴展的方式對任意元素進行反序列化

[英]Using XmlSerializer to deserialize in an extensible fashion with arbitrary elements

我正在使用XmlSerializer反序列化來自遠程API的XML響應。 有許多標准的預定義類,我已經為這些類建立了類。 響應的關鍵部分如下所示:

<data>
    <employee>
        <name>John Doe</name>
        <id>E1</id>
        ....
    </employee>
    <employee>
        ....
    </employee>
    ....
</data>

要么

<data>
    <customer>
        <name>Yoyodyne Systems</name>
        <id>C1</id>
        ....
    </customer>
    <customer>
        ....
    </customer>
    ....
</data>

所以我有Customer和Employee類,而Data類具有如下定義的屬性:

    [XmlElement("customer", typeof(Customer))]
    public List<Customer> Customers { get; set; }

    [XmlElement("employee", typeof(Employee))]
    public List<Employee> Employees { get; set; }

數據元素每個結果只包含一種類型的標記,而且我通常知道期望從給定請求中返回哪種標記,因此我只訪問該屬性,而忽略其他留空的屬性。

但是我想使它更具可擴展性。 特別是遠程應用程序中可能有不同的實例,其中包含自定義類,我不想將它們全部放入基本代碼包中。 我希望可以將屬性添加到Data類中,例如

    public List<object> ExtensionObjects { get; set; }

然后使用XmlSerializer(Type, Type[])構造函數提供要反序列化的實際類型。 但是,我不知道如何告訴它將其應用於任何未知標簽,甚至指定標簽。 例如,如果我有一個自定義Office類,如何使<office>...</office>標記反序列化到其中? 有沒有一種方法可以用XmlSerializer做到這一點,而不必一直回到將所有內容解析為XDocument的方式?

編輯:

似乎有希望的一件事是嘗試處理OnUnknownElement事件。 我可以為其創建一個委托,然后將其通過XmlDeserializationEvents對象傳遞給Deserialize方法調用。 現在,我只需要找出將那些未知元素轉換為擴展類實例的最佳方法。

我已經確定了執行此操作的一種方法,盡管當然可能會有更好的方法。

如上所述,為OnUnknownElement設置處理程序:

XmlDeserializationEvents events = new XmlDeserializationEvents();
events.OnUnknownElement = delegate(object sender, XmlElementEventArgs args)
{
    if (args.Element.Name == "office")
    {
        var data = (Data) args.ObjectBeingDeserialized;
        var item = new Office(args.Element);
        data.ExtensionObjects.Add(item);
    }
};
var response = (Response) serializer.Deserialize(xmlReader, events);

然后,您所需要做的就是實現構造函數,以將XmlElement轉換為對象。 可能有一種更簡潔的方法,但是考慮到這是一個簡單的對象(只是“ name”和“ id”屬性),我只是假設該元素只是命名元素的平面列表。

public Office(XmlElement e)
{
    var valDict = e.ChildNodes.Cast<XmlNode>().Where(n => n is XmlElement)
                   .ToDictionary(x => x.Name, x => x.InnerText);

    Name = valDict["name"];
    Id = valDict["id"];
}

如果有更好的方法可以再次通過XmlSerializer,則無法找到它,因為我無法將XmlElement轉換為XmlReader或Deserialize方法可以接受的任何其他功能。我想我可能再次將其序列化為文本,然后重新解析,但這似乎很麻煩。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM