WCF序列化基本概念詳談
WCF框架在開發人員眼中是一個非常實用的開發工具。它可以幫助我們實現跨平臺的解決方案。在這篇文章中,我們可以了解到有關WCF序列化的一些概念。#t#
大家知道,WCF內置了兩種WCF序列化,DataContractSerializer和NetDataContractSerializer。WCF序列化的基本概念Artech兄已經說得很清楚了,在此不再贅述,本文僅就此二者的區別作一番探討。
先來看看兩者的聲明:
- public sealed class DataContractSerializer :
XmlObjectSerializer{ public
DataContractSerializer(Type type); - … public override object ReadObject
(XmlReader reader); - public object ReadObject(Stream stream);
- public void WriteObject(Stream
stream, object graph); - public override void WriteObject
(XmlWriter writer, object graph); … }
- public sealed class NetDataContractSerializer
: XmlObjectSerializer, IFormatter
{ public NetDataContractSerializer(); - … public object Deserialize(Stream stream);
- public void Serialize(Stream stream, object graph);
- public override object ReadObject(XmlReader reader);
- public object ReadObject(Stream stream);
- public void WriteObject(Stream stream, object graph);
- public override void WriteObject
(XmlWriter writer, object graph); …}
其中兩者的ReadObject(Straem)、WriteObject(Stream, object)的實現繼承自基類XmlObjectSerializer,其他方法均為已覆寫或實現。
從兩個類型的聲明中可以看出NetDataContractSerializer實現了IFormatter接口,而DataContractSerializer沒有,因此只有NetDataContractSerializer能使用.NET基礎結構中的WCF序列化,而DataContractSerializer則是專用于WCF的。
還有一個細節DataContractSerializer的Constructor有一個Type類型的參數,而NetDataContractSerializer沒有。這可蘊藏著深意啊,讀者接著看就明白了。
現在,再來看看此二者的***關鍵區別吧!從一個示例開始吧:
- [DataContract]public class Sub
- { // Fields [DataMember] public int Id;
- [DataMember] public string Name;
- // Methods
- public Sub() {}
- public Sub(int id, string name)
- { this.Id = id; this.Name = name; }}
以上是一個再簡單不過的DataContract的,把他給序列化看看出來些啥。
先用DataContractSerializer序列化:
- Sub sub = new Sub(9, "nine");
- DataContractSerializer dcs =
new DataContractSerializer(typeof(Sub));- MemoryStream stream = new MemoryStream();
- dcs.WriteObject(stream, sub);
- byte[] buf = stream.ToArray();
- string str = Encoding.
UTF8.GetString(buf, 0, buf.Length);
執行完以上代碼后,str的值為:
- < Sub
- xmlns="http://schemas.datacontract
.org/2004/07/ServiceInterface"- xmlns:i="http://www.w3.org/
2001/XMLSchema-instance">- < Id>10
- < /Id>
- < Name>nine
- < /Name>
- < /Sub>
恩,此SOAP消息那是相當得正常。然后將同一個對象用NetDataContractSerializer序列化:
- NetDataContractSerializer
- ndcs = new NetDataContract
Serializer();- MemoryStream nstream =
new MemoryStream();- ndcs.WriteObject(nstream, sub);
- byte[] nbuf = nstream.ToArray();
- string nstr = Encoding.
UTF8.GetString(nbuf, 0, nbuf.Length);
觀察一下nstr的值:
- < Sub z:Id="1"
- z:Type="ServiceInterface.Sub"
- z:Assembly="ServiceInterface,
Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null"- xmlns="http://schemas.datacontract.org/
2004/07/ServiceInterface"- xmlns:i="http://www.w3.org/2001/
XMLSchema-instance"- xmlns:z="http://schemas.microsoft.
com/2003/10/Serialization/">- < Id>10< /Id>
- < Name z:Id="2">nine< /Name>
- < /Sub>
發現了嗎?撇開xml命名空間不說,Sub元素多了Type,Assembly和Id,Name屬性也多了個Id。信息完整多了~~,現在就可以解釋兩者Constructor的區別了,DataContractSerializer是按照SOA的datacontract協議(與SOAP基本一直)來序列化對象的,它并不包含平臺相關的信息,比如類型,程序集等。
所以比如在創建WCF序列化時就提供將要序列化和反系列化的類型信息,DataContractSerializer無法工作。而NetDataContractSerializer則大大擴充了SOAP,為它添加了程序集、類型名等附加信息,這樣一來,序列化器可以完全由序列化的內容來準確推斷將要構造的對象,而不必依賴Constructor所提供的類型參數了。這就是兩者Constructor不同的原因。