XmlSerializer 將 xsi:type 替換為節點名稱
目前 XmlSerializer 產生以下結構:
<config> <BaseType xsi:type="DerivedType1" /> <BaseType xsi:type="DerivedType2" /> </config>有沒有辦法讓它把類型名稱放入節點:
<config> <DerivedType1 /> <DerivedType2 /> </config>?
使用
XmlElementAttribute建構子重載(string elementName, Type type)。它允許您根據在成員中找到的實際類型替換元素名稱。如果您有多個派生類型,請將其中幾個堆疊在一起。如果您嘗試序列化
List<Base>可能包含 Derived 實例的通用集合,則以XmlArrayItem相同的方式使用。以這種方式定義也隱式使派生類型已知,因此
XmlInclude不需要屬性樣本定義:
[XmlRoot] public class Data { [XmlElement("Derived1", typeof(Derived1))] [XmlElement("Derived2", typeof(Derived2))] public Base foo { get; set; } [XmlArrayItem("Derived1", typeof(Derived1))] [XmlArrayItem("Derived2", typeof(Derived2))] public List<Base> fooList { get; set; } } public class Base { ... } public class Derived1 : Base { ... } public class Derived2 : Base { ... }
為什麼人們總是說“你永遠無法反序列化”。這絕對是錯誤的。
public class BaseClass { public string Name {get;set;} } [XmlRoot("BaseClass")] public class ChildClass : BaseClass { public int Value {get;set;} } [XmlRoot("BaseClass")] public class FlatClass { public string Name {get;set;} public int Value {get;set;} } XmlSerializer ser1 = new XmlSerializer(typeof(BaseClass)); XmlSerializer ser2 = new XmlSerializer(typeof(ChildClass)); XmlSerializer ser3 = new XmlSerializer(typeof(FlatClass)); ser1.Serialize(File.Open("ser1.xml", FileMode.Create), new BaseClass(){Name="Base"}); ser2.Serialize(File.Open("ser2.xml", FileMode.Create), new ChildClass(){Name="Child",Value = 1}); ser1.Deserialize(File.OpenRead("ser2.xml")); ser2.Deserialize(File.OpenRead("ser1.xml")); ser3.Deserialize(File.OpenRead("ser2.xml"));繁榮。工作得很好!!!!序列化在這三個方面都完美無缺。生成的對像在任一側可能都不是 100%,但它確實會反序列化。Ser1 在反序列化 ser2.xml 時忽略 Value 元素 Ser2 在反序列化 ser1.xml 時跳過 Value 屬性
唯一打破這個模型的是:
ser1.Serailize(File.Open("ser3.xml", FileMode.Create), new ChildClass(){Name = "Child2", Value = 2}); XmlSerialize ser3 = new XmlSerializer(typeof(FlatClass)); ser3.Deserialize(File.OpenRead("ser3.xml"));最後一次中斷,因為 BaseClass 的序列化程序遵循在元素上包含 xsi:type=“ChildClass” 屬性的模式標準(儘管這是一個有價值的和 99% 的時間標準)。Ser3 無法處理該類型,因為它與該類型無關,特別是如果 FlatClass 存在於跨 WAN 或 LAN 線路的另一個程序集中。就像 Honey-badger 一樣,XmlSerailizer 不關心元素或值,只要它可以找到它們並且架構中的任何內容都不會破壞該過程。XSI:TYPE 屬性會破壞模式。
例如,當使用 WCF 或其他基於 XML 通信的系統時,如果服務有一個名為 FlatClass 的類,它不會反序列化包含 xsi:type="" 屬性的 ChildClass。但是,如果您不使用 BaseClass 的序列化程序,它將反序列化完全相同的 XML 而沒有該 xsi:type 屬性。
QED不包括 xsi:type 屬性通常是有益的、必要的和可取的。
話雖如此,有沒有辦法為 BaseClass 類型創建一個 XmlSerializer 並告訴它在序列化子類型時不要包含 xsi:type 屬性?
感謝 Jaeden “Sifo Dyas” al’Raec Ruiner