[英]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.