我的WCF之旅(4):WCF中的序列化[下篇]

本文轉載自:http://www.cnblogs.com/artech/archive/2007/03/10/670446.html 作者:artech 轉載請註明該聲明。

... ...續Part I([原創] 我的WCF之旅(4):WCF中的序列化(Serialization)- Part I)

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
24a924a57ba6b3f2b51fc9edb7ea4186.jpe9310e85a14af99de4811ff4c77f1f911.jpe
{
    
public class XMLProduct
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe    
{
e083dfde5a91f50979fe8979b4012b9d.jpe715f2d05503b99d41f3b6ba2cdccc84d.jpe        
Private Fields#region Private Fields
        
private Guid _productID;
        
private string _productName;
        
private string _producingArea;
        
private double _unitPrice;
       
e083dfde5a91f50979fe8979b4012b9d.jpe715f2d05503b99d41f3b6ba2cdccc84d.jpe        
Constructors#region Constructors
        
public XMLProduct()
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
            Console.WriteLine(
"The constructor of XMLProduct has been invocated!");
        }


        
public XMLProduct(Guid id, string name, string producingArea, double price)
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
            
this._productID = id;
            
this._productName = name;
            
this._producingArea = producingArea;
            
this._unitPrice = price;
        }


        
#endregion


e083dfde5a91f50979fe8979b4012b9d.jpe715f2d05503b99d41f3b6ba2cdccc84d.jpe        
Properties#region Properties
        
public Guid ProductID
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _productID; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _productID = value; }
        }


        
public string ProductName
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _productName; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _productName = value; }
        }


        
internal string ProducingArea
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _producingArea; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _producingArea = value; }
        }


        
public double UnitPrice
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _unitPrice; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _unitPrice = value; }
        }


       
#endregion


    }

}



using  System;
using  System.Collections.Generic;
using  System.Text;

namespace  Artech.WCFSerialization
24a924a57ba6b3f2b51fc9edb7ea4186.jpe9310e85a14af99de4811ff4c77f1f911.jpe
{
    
public class XMLOrder
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe    
{
        
private Guid _orderID;
        
private DateTime _orderDate;
        
private XMLProduct _product;
        
private int _quantity;

e083dfde5a91f50979fe8979b4012b9d.jpe715f2d05503b99d41f3b6ba2cdccc84d.jpe        
Constructors#region Constructors
        
public XMLOrder()
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
            
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)
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
            
this._orderID = id;
            
this._orderDate = date;
            
this._product = product;
            
this._quantity = quantity;
        }

        
#endregion


e083dfde5a91f50979fe8979b4012b9d.jpe715f2d05503b99d41f3b6ba2cdccc84d.jpe        
Properties#region Properties
        
public Guid OrderID
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _orderID; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _orderID = value; }
        }


        
public DateTime OrderDate
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _orderDate; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _orderDate = value; }
        }


        
public XMLProduct Product
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _product; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _product = value; }
        }


        
public int Quantity
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _quantity; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _quantity = value; }
        }

        
#endregion


        
public override string ToString()
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
            
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.

9310e85a14af99de4811ff4c77f1f911.jpe24a924a57ba6b3f2b51fc9edb7ea4186.jpe
static void SerializeViaXMLSerializer()
24a924a57ba6b3f2b51fc9edb7ea4186.jpe9310e85a14af99de4811ff4c77f1f911.jpe        
{
            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))
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
{
                XmlSerializer serializer 
= new XmlSerializer(typeof(XMLOrder));
                
using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(fs))
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe                
{
                    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關係:

  1. Root Element被指定爲類名。
  2. 不會再Root Element中添加相應的Namaspace。
  3. 對象成員以XML Element的形式輸出。
  4. 對象成員出現的順利和在Type定義的順序一致。
  5. 只有Public Field和可讀可寫得Proppery纔會被序列化到XML中——比如定義在XMLProduct中的internal string ProducingArea沒有出現在XML中。
  6. Type定義的時候不需要運用任何Attribute。

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

  1. Root Element名稱之後能爲類名。
  2. 可以在Type上運用XMLRoot,通過Namaspace參數在Root Element指定Namespace。
  3. 可以通過在類成員上運用XMLElement Attribute和XMLAttribute Attribute指定對象成員轉化成XMLElement還是XMLAttribute。並且可以通過NameSpace參數定義Namespace。
  4. 可以在XMLElement或者XMLAttribute Attribute 通過Order參數指定成員在XML出現的位置。
  5. 可以通過XmlIgnore attribute阻止對象成員被序列化。

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

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Xml.Serialization;

namespace  Artech.WCFSerialization
24a924a57ba6b3f2b51fc9edb7ea4186.jpe9310e85a14af99de4811ff4c77f1f911.jpe
{
    
public class XMLProduct
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe    
{
e083dfde5a91f50979fe8979b4012b9d.jpe715f2d05503b99d41f3b6ba2cdccc84d.jpe        
Private Fields#region Private Fields
        
private Guid _productID;
        
private string _productName;
        
private string _producingArea;
        
private double _unitPrice;
        
#endregion


e083dfde5a91f50979fe8979b4012b9d.jpe715f2d05503b99d41f3b6ba2cdccc84d.jpe        
Constructors#region Constructors
        
public XMLProduct()
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
            Console.WriteLine(
"The constructor of XMLProduct has been invocated!");
        }


        
public XMLProduct(Guid id, string name, string producingArea, double price)
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
            
this._productID = id;
            
this._productName = name;
            
this._producingArea = producingArea;
            
this._unitPrice = price;
        }


        
#endregion


e083dfde5a91f50979fe8979b4012b9d.jpe715f2d05503b99d41f3b6ba2cdccc84d.jpe        
Properties#region Properties
        [XmlAttribute(
"id")]
        
public Guid ProductID
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _productID; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _productID = value; }
        }


        [XmlElement(
"name")]
        
public string ProductName
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _productName; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _productName = value; }
        }

        [XmlElement(
"producingArea")]
        
public string ProducingArea
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _producingArea; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _producingArea = value; }
        }


        [XmlElement(
"price")]
        
public double UnitPrice
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _unitPrice; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _unitPrice = value; }
        }


#endregion


    }

}


using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Xml.Serialization;

namespace  Artech.WCFSerialization
24a924a57ba6b3f2b51fc9edb7ea4186.jpe9310e85a14af99de4811ff4c77f1f911.jpe
{
    [XmlRoot(Namespace 
= "http://artech.wcfSerialization/Samples/Order")]
    
public class XMLOrder
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe    
{
        
private Guid _orderID;
        
private DateTime _orderDate;
        
private XMLProduct _product;
        
private int _quantity;

e083dfde5a91f50979fe8979b4012b9d.jpe715f2d05503b99d41f3b6ba2cdccc84d.jpe        
Constructors#region Constructors
        
public XMLOrder()
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
            
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)
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
            
this._orderID = id;
            
this._orderDate = date;
            
this._product = product;
            
this._quantity = quantity;
        }

        
#endregion


e083dfde5a91f50979fe8979b4012b9d.jpe715f2d05503b99d41f3b6ba2cdccc84d.jpe        
Properties#region Properties
        [XmlAttribute(
"id")]
        
public Guid OrderID
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _orderID; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _orderID = value; }
        }

        [XmlElement(ElementName 
= "date",Order = 3)]
        
public DateTime OrderDate
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _orderDate; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _orderDate = value; }
        }

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


        [XmlElement(ElementName 
= "quantity", Order = 2)]
        
public int Quantity
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
get return _quantity; }
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
set { _quantity = value; }
        }

        
#endregion


        
public override string ToString()
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe        
{
            
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。

9310e85a14af99de4811ff4c77f1f911.jpe24a924a57ba6b3f2b51fc9edb7ea4186.jpe
static void DeserializeViaXMLSerializer()
24a924a57ba6b3f2b51fc9edb7ea4186.jpe9310e85a14af99de4811ff4c77f1f911.jpe        
{
           
string fileName = _basePath + "Order.XmlSerializer.xml";
           XMLOrder order;
           
using (FileStream fs = new FileStream(fileName, FileMode.Open))
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe            
{
                XmlSerializer serializer 
= new XmlSerializer(typeof(XMLOrder), "http://artech.WCFSerialization/Samples");
                
using (XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas()))
715f2d05503b99d41f3b6ba2cdccc84d.jpee083dfde5a91f50979fe8979b4012b9d.jpe                
{
                    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

調用默認構造函數

不會調用



WCF相關內容:
[原創]我的WCF之旅(1):創建一個簡單的WCF程序
[原創]我的WCF之旅(2):Endpoint Overview
[原創]我的WCF之旅(3):在WCF中實現雙向通信(Bi-directional Communication)
[原創]我的WCF之旅(4):WCF中的序列化(Serialization)- Part I
[原創]我的WCF之旅(4):WCF中的序列化(Serialization)- Part II
[原創]我的WCF之旅(5):Service Contract中的重載(Overloading)
[原創]我的WCF之旅(6):在Winform Application中調用Duplex Service出現TimeoutException的原因和解決方案
[原創]我的WCF之旅(7):面向服務架構(SOA)和麪向對象編程(OOP)的結合——如何實現Service Contract的繼承
[原創]我的WCF之旅(8):WCF中的Session和Instancing Management
[原創]我的WCF之旅(9):如何在WCF中使用tcpTrace來進行Soap Trace
[原創]我的WCF之旅(10): 如何在WCF進行Exception Handling
[原創]我的WCF之旅(11):再談WCF的雙向通訊-基於Http的雙向通訊 V.S. 基於TCP的雙向通訊

[原創]我的WCF之旅(12):使用MSMQ進行Reliable Messaging
[原創]我的WCF之旅(13):創建基於MSMQ的Responsive Service
發佈了0 篇原創文章 · 獲贊 49 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章