首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WCF 序列化深度解析(四):XMLSerializer 與 DataContractSerializer 的詳細比較(下)

     編輯:關於.NET

XMLSerializer 簡介

XMLSerializer 是早期 ASMX Web Service 預設的序列化器,許多開發者對它並不陌生。為了理解其映射機制,我們先透過範例觀察 Managed Type 結構與生成 XML 的對應關係。範例中定義了 XMLProduct 與 XMLOrder 兩個類別,其成員結構與前一篇提到的 DataContract 版本相同。

預設序列化行為

以下程式碼示範如何使用 XMLSerializer 進行序列化:

static void SerializeViaXMLSerializer()
{
    XMLProduct product = new XMLProduct(Guid.NewGuid(), "Dell PC", "Xiamen FuJian", 4500);
    XMLOrder order = new XMLOrder(Guid.NewGuid(), DateTime.Today, product, 300);
    string fileName = _basePath + "Order.XmlSerializer.xml";
    using (FileStream fs = new FileStream(fileName, FileMode.Create))
    {
        XmlSerializer serializer = new XmlSerializer(typeof(XMLOrder));
        using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(fs))
        {
            serializer.Serialize(writer, order);
        }
    }
    Process.Start(fileName);
}

執行後產生的 XML 如下:

<?xml version="1.0" encoding="utf-8"?>
<XMLOrder xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="https://www.w3.org/2001/XMLSchema">
  <OrderID>b695fd18-9cd7-4792-968a-0c0c3a3962c2</OrderID>
  <OrderDate>2007-03-09T00:00:00+08:00</OrderDate>
  <Product>
    <ProductID>23a2fe03-d0a0-4ce5-b213-c7e5196af566</ProductID>
    <ProductName>Dell PC</ProductName>
    <UnitPrice>4500</UnitPrice>
  </Product>
  <Quantity>300</Quantity>
</XMLOrder>

由此可總結 XMLSerializer 的預設映射規則:

  • 根元素名稱即為類別名稱。
  • 根元素不會自動加入命名空間。
  • 物件成員以 XML 元素形式輸出。
  • 成員出現順序與類別定義順序一致。
  • 只有 public 欄位與可讀寫的屬性會被序列化(例如 internal string ProducingArea 就被忽略)。
  • 類別定義時不需套用任何屬性。

透過屬性自訂映射

與 DataContractSerializer 類似,XMLSerializer 也提供屬性來調整預設行為:

  • [XmlRoot]:指定根元素名稱與命名空間。
  • [XmlElement] 與 [XmlAttribute]:控制成員輸出為元素或屬性,並可設定名稱、命名空間與順序(Order 參數)。
  • [XmlIgnore]:排除特定成員不參與序列化。

套用屬性後的類別定義如下:

[XmlRoot(Namespace = "https://artech.wcfSerialization/Samples/Order")]
public class XMLOrder
{
    [XmlAttribute("id")]
    public Guid OrderID { get; set; }

    [XmlElement(ElementName = "date", Order = 3)]
    public DateTime OrderDate { get; set; }

    [XmlElement(ElementName = "product", Order = 1, Namespace = "Http://Artech.WCFSerialization/Samples/Product")]
    public XMLProduct Product { get; set; }

    [XmlElement(ElementName = "quantity", Order = 2)]
    public int Quantity { get; set; }
    // ... 建構函式與 ToString 省略
}

public class XMLProduct
{
    [XmlAttribute("id")]
    public Guid ProductID { get; set; }

    [XmlElement("name")]
    public string ProductName { get; set; }

    [XmlElement("producingArea")]
    public string ProducingArea { get; set; }

    [XmlElement("price")]
    public double UnitPrice { get; set; }
    // ... 建構函式省略
}

再次序列化後,XML 結構變更為:

<?xml version="1.0" encoding="utf-8"?>
<XMLOrder id="9a0bbda4-1743-4398-bc4f-ee216e02695b" xmlns="https://artech.wcfSerialization/Samples/Order" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="https://www.w3.org/2001/XMLSchema">
  <product id="4e3aabe5-3a51-4000-9fd8-d821d164572a" xmlns="Http://Artech.WCFSerialization/Samples/Product">
    <name>Dell PC</name>
    <producingArea>Xiamen FuJian</producingArea>
    <price>4500</price>
  </product>
  <quantity>300</quantity>
  <date>2007-03-09T00:00:00+08:00</date>
</XMLOrder>

反序列化行為差異

反序列化程式碼如下:

static void DeserializeViaXMLSerializer()
{
    string fileName = _basePath + "Order.XmlSerializer.xml";
    XMLOrder order;
    using (FileStream fs = new FileStream(fileName, FileMode.Open))
    {
        XmlSerializer serializer = new XmlSerializer(typeof(XMLOrder), "https://artech.WCFSerialization/Samples");
        using (XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()))
        {
            order = serializer.Deserialize(reader) as XMLOrder;
        }
    }
    Console.WriteLine(order);
    Console.Read();
}

執行結果顯示,反序列化時會呼叫無參數建構函式(輸出 "The constructor of XMLProduct has been invocated!" 等訊息)。這與 DataContractSerializer 不會呼叫建構函式 形成鮮明對比。

DataContractSerializer 與 XMLSerializer 比較總結

特性XMLSerializerDataContractSerializer
預設映射對象所有 public 欄位與可讀寫屬性標記 [DataMember] 的欄位/屬性
是否需屬性不需要需 [DataContract] 與 [DataMember](或 [Serializable])
成員預設順序類別定義順序字母排序
相容性ASMX、RemotingWCF 預設
反序列化是否呼叫建構函式是否

選擇哪種序列化器取決於專案需求:若需與舊版 ASMX 相容或需精細控制 XML 結構(如屬性與元素混用),XMLSerializer 較適合;若追求效能、支援版本容忍、且不需呼叫建構函式,DataContractSerializer 則是 WCF 的首選。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved