程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 我的WCF之旅(4):WCF中的序列化(Serialization)- Part II

我的WCF之旅(4):WCF中的序列化(Serialization)- Part II

編輯:關於.NET

XMLSerializer

提到XMLSerializer,我想絕大多數人都知道這是asmx采用的Serializer。首先我們還是來看一個例子,通過比較Managed Type的結構和生成的XML的結構來總結這種序列化方式采用的是怎樣的一種Mapping方式。和DataContractSerialzer Sample一樣,我們要定義用於序列化對象所屬的Type——XMLOrder和XMLProduct,他們和相面對應的DataContractOrder和DataContractProduct具有相同的成員。

using System;
using System.Collections.Generic;
using System.Text;
namespace Artech.WCFSerialization
{
  public class XMLProduct
  {
    Private Fields#region Private Fields
    private Guid _productID;
    private string _productName;
    private string _producingArea;
    private double _unitPrice;
    Constructors#region Constructors
    public XMLProduct()
    {
      Console.WriteLine("The constructor of XMLProduct has been invocated!");
    }
    public XMLProduct(Guid id, string name, string producingArea, double price)
    {
      this._productID = id;
      this._productName = name;
      this._producingArea = producingArea;
      this._unitPrice = price;
    }
    #endregion
    Properties#region Properties
    public Guid ProductID
    {
      get { return _productID; }
      set { _productID = value; }
    }
    public string ProductName
    {
      get { return _productName; }
      set { _productName = value; }
    }
    internal string ProducingArea
    {
      get { return _producingArea; }
      set { _producingArea = value; }
    }
    public double UnitPrice
    {
      get { return _unitPrice; }
      set { _unitPrice = value; }
    }
    #endregion
  }
}
using System;
using System.Collections.Generic;
using System.Text;
namespace Artech.WCFSerialization
{
  public class XMLOrder
  {
    private Guid _orderID;
    private DateTime _orderDate;
    private XMLProduct _product;
    private int _quantity;
    Constructors#region Constructors
    public XMLOrder()
    {
      this._orderID = new Guid();
      this._orderDate = DateTime.MinValue;
      this._quantity = int.MinValue;
      Console.WriteLine("The constructor of XMLOrder has been invocated!");
    }
    public XMLOrder(Guid id, DateTime date, XMLProduct product, int quantity)
    {
      this._orderID = id;
      this._orderDate = date;
      this._product = product;
      this._quantity = quantity;
    }
    #endregion
    Properties#region Properties
    public Guid OrderID
    {
      get { return _orderID; }
      set { _orderID = value; }
    }
    public DateTime OrderDate
    {
      get { return _orderDate; }
      set { _orderDate = value; }
    }
    public XMLProduct Product
    {
      get { return _product; }
      set { _product = value; }
    }
    public int Quantity
    {
      get { return _quantity; }
      set { _quantity = value; }
    }
    #endregion
    public override string ToString()
    {
      return string.Format("ID: {0}\nDate:{1}\nProduct:\n\tID:{2}\n\tName:{3}\n\tProducing Area:{4}\n\tPrice:{5}\nQuantity:{6}",
        this._orderID,this._orderDate,this._product.ProductID,this._product.ProductName,this._product.ProducingArea,this._product.UnitPrice,this._quantity);
    }
  }
}

編寫Serialization的Code.

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="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://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>

這裡我們總結出以下的Mapping關系:

Root Element被指定為類名。

不會再Root Element中添加相應的Namaspace。

對象成員以XML Element的形式輸出。

對象成員出現的順利和在Type定義的順序一致。

只有Public Field和可讀可寫得Proppery才會被序列化到XML中——比如定義在XMLProduct中的internal string ProducingArea沒有出現在XML中。

Type定義的時候不需要運用任何Attribute。

以上這些都是默認的Mapping關系,同DataContractSerializer一樣,我們可以通過在Type以及它的成員中運用一些Attribute來改這種默認的Mapping。

Root Element名稱之後能為類名。

可以在Type上運用XMLRoot,通過Namaspace參數在Root Element指定Namespace。

可以通過在類成員上運用XMLElement Attribute和XMLAttribute Attribute指定對象成員轉化成XMLElement還是XMLAttribute。並且可以通過NameSpace參數定義Namespace。

可以在XMLElement或者XMLAttribute Attribute 通過Order參數指定成員在XML出現的位置。

可以通過XmlIgnore attribute阻止對象成員被序列化。

基於上面這些,我們重新定義了XMLProduct和XMLOrder。

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
namespace Artech.WCFSerialization
{
  public class XMLProduct
  {
    Private Fields#region Private Fields
    private Guid _productID;
    private string _productName;
    private string _producingArea;
    private double _unitPrice;
    #endregion
    Constructors#region Constructors
    public XMLProduct()
    {
      Console.WriteLine("The constructor of XMLProduct has been invocated!");
    }
    public XMLProduct(Guid id, string name, string producingArea, double price)
    {
      this._productID = id;
      this._productName = name;
      this._producingArea = producingArea;
      this._unitPrice = price;
    }
    #endregion
    Properties#region Properties
    [XmlAttribute("id")]
    public Guid ProductID
    {
      get { return _productID; }
      set { _productID = value; }
    }
    [XmlElement("name")]
    public string ProductName
    {
      get { return _productName; }
      set { _productName = value; }
    }
    [XmlElement("producingArea")]
    public string ProducingArea
    {
      get { return _producingArea; }
      set { _producingArea = value; }
    }
    [XmlElement("price")]
    public double UnitPrice
    {
      get { return _unitPrice; }
      set { _unitPrice = value; }
    }
#endregion
  }
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
namespace Artech.WCFSerialization
{
  [XmlRoot(Namespace = "http://artech.wcfSerialization/Samples/Order")]
   public class XMLOrder
  {
    private Guid _orderID;
    private DateTime _orderDate;
    private XMLProduct _product;
    private int _quantity;
    Constructors#region Constructors
    public XMLOrder()
    {
      this._orderID = new Guid();
      this._orderDate = DateTime.MinValue;
      this._quantity = int.MinValue;
      Console.WriteLine("The constructor of XMLOrder has been invocated!");
    }
    public XMLOrder(Guid id, DateTime date, XMLProduct product, int quantity)
    {
      this._orderID = id;
      this._orderDate = date;
      this._product = product;
      this._quantity = quantity;
    }
    #endregion
    Properties#region Properties
    [XmlAttribute("id")]
    public Guid OrderID
    {
      get { return _orderID; }
      set { _orderID = value; }
    }
    [XmlElement(ElementName = "date",Order = 3)]
    public DateTime OrderDate
    {
      get { return _orderDate; }
      set { _orderDate = value; }
    }
    [XmlElement(ElementName = "product", Order = 1, Namespace = "Http://Artech.WCFSerialization/Samples/Product")]
     public XMLProduct Product
    {
      get { return _product; }
      set { _product = value; }
    }
    [XmlElement(ElementName = "quantity", Order = 2)]
    public int Quantity
    {
      get { return _quantity; }
      set { _quantity = value; }
    }
    #endregion
    public override string ToString()
    {
      return string.Format("ID: {0}\nDate:{1}\nProduct:\n\tID:{2}\n\tName:{3}\n\tProducing Area:{4}\n\tPrice:{5}\nQuantity:{6}",
        this._orderID,this._orderDate,this._product.ProductID,this._product.ProductName,this._product.ProducingArea,this._product.UnitPrice,this._quantity);
    }
  }
}

重新進行一次Serialization。我們可以得到下面的XML。

<?xml version="1.0" encoding="utf-8"?>
<XMLOrder id="9a0bbda4-1743-4398-bc4f-ee216e02695b" xmlns="http://artech.wcfSerialization/Samples/Order" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://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>

分析完XMLSerializer的Serialization功能,我們照例來分析它的反向過程—Deserialization。下面的Deserialization的Code。

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), "http://artech.WCFSerialization/Samples");
         using (XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()))
        {
          order= serializer.Deserialize(reader) as XMLOrder;
        }
      }
      Console.WriteLine(order);
      Console.Read();
}

調用DeserializeViaXMLSerializer,得到下面的Screen Shot。下面顯示的Order對象的信息和我們利用DataContractSerializaer進行Deserialization是的輸出沒有什麼兩樣。不過有趣的是上面多出了兩行額外的輸出:The constructor of XMLProduct has been invocated! The constructor of XMLOrder has been invocated。而這個操作實際上是定義在XMLProduct和XMLOrder的默認(無參)構造函數裡的。所此我們可以得出這樣的結論——用XMLSerializer進程Deserialization,會調用的默認(無參)構造函數來初始化對象。

DataContractSerializer V.S.XMLSerializer

上面我們分別分析了兩種不同的Serializer,現在我們來簡單總結一下他們的區別:

特性 XMLSerializer DataContractSerializer 默認Mapping 所有Public Field和可讀可寫Property 所有DataMember Filed、Property 是否需要Attribute 不需要 DataContract DataMember或者Serializable 成員的默認次序 Type中定義的順序 字母排序 兼容性 .asmx Remoting Deserialzation 調用默認構造函數 不會調用

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved