程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 《WCF技術內幕》22:第2部分_第5章_消息:XmlDictionaryWriter

《WCF技術內幕》22:第2部分_第5章_消息:XmlDictionaryWriter

編輯:關於.NET

(概述:這一部分介紹了XmlDictionaryWriter類型的相關概念:如何創建, 使用一個對象,然後講述了如何進行Text、二進制和MTOM編碼。最後介紹了 XmlDictionary的作用【老徐備注2】,已經各種編碼的效率問題。你會了解為 WCF支持的幾種編碼格式的基本原理。)

XmlDictionaryWriter

XmlDictionaryWriter類型為Message類型的序列化和編碼的。它繼承自 System.Xml.XmlWriter,因此繼承了很多XmlWriter 的屬性。像XmlWriter一樣 ,XmlDictionaryWriter也是抽象類型,它定義了幾個返回XmlDictionaryWriter 子類型實例的方法,包裝了System.IO.Stream並且定義了許多以Write單詞開始 的方法。在作用上,程序裡使用 XmlDictionaryWriter和XmlWriter在概念上十 分相似。

與XmlWriter不同,XmlDictionaryWriter類型的目的是序列化和編碼Message 對象,並且有時會使用XmlDictionary對象處理壓縮工作。為了這一目的, XmlDictionaryWriter 類型定義了一些與XmlWriter不同的成員。讓我們通過研 究這些成員來詳細了解一下XmlDictionaryWriter類型。首先我們會檢查一下 XmlDictionaryWriter的構造函數,然後看看如何通過Stream序列化和編碼XML數 據。

創建一個XmlDictionaryWriter對象

XmlDictionaryWriter定義了幾個工廠方法,並且它們都直接或者間接地接受 System.IO.Stream對象的引用。這些方法大部分是重載一下4個方法: CreateDictionaryWriter、CreateTextWriter、CreateMtomWriter和 CreateBinaryWriter。

CreateDictionaryWriter  XmlDictionaryWriter 類型上的工廠方法 CreateDictionaryWriter 其中之一就是接受一個XmlWriter類型的引用。內部來 說,這些方法返回的實例都是簡單地包裝了傳遞的參數XmlWriter。因此,這些 方法用處不大,除了某些API裡需要XmlDictionaryWriter類型的時候。比如,你 可能要掉也難怪一個接受XmlDictionaryWriter類型參數的方法,但是你只有一 個XmlWriter類型的局部變量。假如這樣的話,你可以通過調用 CreateDictionaryWriter工廠方法,傳遞XmlWriter參數,從XmlWriter創建 XmlDictionaryWriter對象,代碼如下:

MemoryStream stream = new MemoryStream();
XmlWriter xmlWriter = XmlWriter.Create(stream);
XmlDictionaryWriter writer =  XmlDictionaryWriter.CreateDictionaryWriter(xmlWriter);

CreateTextWriter  XmlDictionaryWriter類型定義了三個工廠方法。這些 工廠方法返回的是繼承自XmlDictionaryWriter類型的實例,並且它們的作用是 為了產生基於文本編碼的XML。所有的三個方法都接受Stream類型的參數。兩個 方法接受一個Stream參數和一個 System.Text.Encoding類型的參數。一個方法 接受一個Stream類型、一個Encoding和一個Boolean類型的參數。 Encoding參數 ,如你所期望的,設置處理Stream時候的編碼格式。雖然有很多編碼格式,但是 CreateTextWriter方法只支持三種編碼格式:UTF-8 、Unicode (UTF-16) little-endian和big-endian方式。如果不選擇的話,默認使用UTF-8編碼。 Boolean參數表示 XmlDictionaryWriter是否擁有這個Stream對象。如果為true, 調用XmlDictionaryWriter上的Close 和Dispose方法,也會調用Stream對象的 Close方法,因此能夠阻止對Stream 的後續訪問。如果沒有設置的話,默認為 true.下面的代碼演示了如何使用CreateTextWriter方法:

MemoryStream stream = new MemoryStream();
using (XmlDictionaryWriter writer =
  XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8,  false)) {
       writer.WriteStartDocument();
       writer.WriteElementString("SongName",
                                 "urn:ContosoRockabilia",
                                 "Aqualung");
       writer.Flush();
}

Console.WriteLine("XmlDictionaryWriter (Text-UTF8) wrote {0}  bytes",
                   stream.Position);
  stream.Position = 0;
  Byte[] bytes = stream.ToArray();
  Console.WriteLine(BitConverter.ToString(bytes));
  Console.WriteLine("data read from stream:\n{0}\n",
     new StreamReader(stream).ReadToEnd());

當代碼運行的時,它會產生下面的輸出:

XmlDictionaryWriter (Text-UTF8) wrote 97 bytes3C-3F-78- 6D-6C-20-76-65-72-73-69-6F-6E-3D-22-31-2E-30-22-20-65-6E-63-6F-64-69- 6E-67-3D-2275-74-66-2D-38-22-3F-3E-3C-53-6F-6E-67-4E-61-6D-65-20-78- 6D-6C-6E-73-3D-22-75-72-6E-3A-436F-6E-74-6F-73-6F-52-6F-63-6B-61-62- 69-6C-69-61-22-3E-41-71-75-61-6C-75-6E-67-3C-2F-53-6F6E-67-4E-61-6D- 65-3E
data read from stream:
<?xml version="1.0" encoding="utf-8"?>
<SongName  xmlns="urn:ContosoRockabilia">Aqualung</SongName>

注意到XmlDictionaryWriter放在Using結構裡,因此可以確保Dispose方法的 被調用。但是Stream對象在using 體結束後依然可用;這可能因為 CreateTextWriter的Boolean參數設置為false了。當使用UTF-8編碼的時候,字 節順序標記(BOM)忽略了。如果選擇Unicode編碼,輸出結果會包含標准的UTF -16 little-endian BOM(FF FE).

CreateMtomWriter  XmlDictionaryWriter定義了兩個CreateMtomWriter方 法。這些方法放回的是繼承自XmlDictionaryWriter並且產生MTOM編碼的XML的實 例。兩者都接受一個Stream類型的參數和幾個別的控制XML Infoset編碼的參數 。這些參數設置編碼格式、SOAP消息頭的ContentType、多用途網絡郵件擴展協 議(MIME)的邊界和MIME的統一資源標識符(URI),同時也包括是否把消息寫 入Stream對象。對於CreateTextWriter方法,支持的編碼是UTF-8 、Unicode (UTF-16) little-endian和big-endian方式。下面代碼演示了如何調用 CreateMtomWriter方法:

MemoryStream stream = new MemoryStream();
using (XmlDictionaryWriter writer =
  XmlDictionaryWriter.CreateMtomWriter(stream, Encoding.UTF8,  1000,
                                         "Application/soap+xml")) {
  writer.WriteStartDocument();
  writer.WriteElementString("SongName",
                             "urn:ContosoRockabilia",
                             "Aqualung");
  writer.Flush();
}
Console.WriteLine("XmlDictionaryWriter (MTOM-UTF8) wrote {0}  bytes",
                    stream.Position);
stream.Position = 0;
Byte[] bytes = stream.ToArray();
Console.WriteLine(BitConverter.ToString(bytes));
Console.WriteLine("data read from stream:\n{0}\n",
     new StreamReader(stream).ReadToEnd());

當代碼執行的時候,它會產生下面的結果。(為了簡潔省略了一些內容。)

XmlDictionaryWriter (MTOM-UTF8) wrote 576 bytes
4D-49-4D-45-2D-56-65-72-73-69-6F-6E-3A-20-31-2E-30-0D-0A-43-6F-6E- 74-65-6E-74-2D-54-79-70
65-3A-20-6D-75-6C-74-69-70-61-72-74-2F-72-65-6C-61-74-65-64-3B-74- 79-70-65-3D-22-61-70-70
6C-69-63-61-74-69-6F-6E-2F-78-6F-70-2B-78-6D-6C-22-3B-62-6F-75-6E- 64-61-72-79-3D-22-37-31
65-37-62-35-32-61-2D-37-61-34-36-2D-34-37-32-36-2D-62-61-62-64-2D- 31-37-37-32-32-39-65-32
38-66-30-33-2B-69-64-3D-31-22-3B-73-74-61-72-74-3D-22-3C-68-74-74- 70-3A-2F-2F-74-65-6D-70
75-72-69-2E-6F-72-67-2F-30-2F-36-33-32-38-37-31-37-34-35-30-37-30- 38-39-31
data read from stream:
MIME-Version: 1.0
Content-Type: multipart/related;
  type="application/xop+xml";
  boundary="+id=1";
  start="<http://tempuri.org/0/632871745070891488>";
  start-info="Application/soap+xml"
--+id=1
Content-ID: <http://tempuri.org/0/632871745070891488>
Content-Transfer-Encoding: 8bit
Content-Type: application/xop+xml; charset=utf-8;
    type="Application/soap+xml"
<?xml version="1.0" encoding="utf-8"?>
  <SongName xmlns="urn:ContosoRockabilia">
     Aqualung
  </SongName>
--+id=1–

下面代碼演示了調用其它的CreateMtomWriter方法產生不同的結果:

MemoryStream stream = new MemoryStream();
using (XmlDictionaryWriter writer =
  XmlDictionaryWriter.CreateMtomWriter(stream,
                                         Encoding.UTF8,
                                         1000,
                                         "startInfo",
                                         "boundary",
                                         "urn:startUri",
                                         false,
                                         false)){
       writer.WriteStartDocument();
       writer.WriteElementString("SongName",
                                 "urn:ContosoRockabilia",
                                 "Aqualung");
       writer.Flush();
  }
Console.WriteLine("XmlDictionaryWriter (MTOM-UTF8) wrote {0}  bytes",
     stream.Position);
stream.Position = 0;
Byte[] bytes = stream.ToArray();
Console.WriteLine(BitConverter.ToString(bytes));
Console.WriteLine("data read from stream:\n{0}\n",
  new StreamReader(stream).ReadToEnd());

當代碼執行的時候,它會產生下面的結果。(為了簡潔省略了一些內容。)

XmlDictionaryWriter (MTOM-UTF8) wrote 256 bytes
0D-0A-2D-2D-62-6F-75-6E-64-61-72-79-0D-0A-43-6F-6E-74-65-6E-74-2D- 49-44-3A-20-3C-75-72-6E
3A-73-74-61-72-74-55-72-69-3E-0D-0A-43-6F-6E-74-65-6E-74-2D-54-72- 61-6E-73-66-65-72-2D-45
6E-63-6F-64-69-6E-67-3A-20-38-62-69-74-0D-0A
data read from stream:

--boundary
Content-ID: <urn:startUri>
Content-Transfer-Encoding: 8bit
Content-Type: application/xop+xml;charset=utf- 8;type="startInfo"

<?xml version="1.0" encoding="utf-8"?>
<SongName xmlns="urn:ContosoRockabilia">
  Aqualung
</SongName>
--boundary–

注意到第二個CreateMtomWriter方法的參數映射到MTOM編碼數據的不同位置 。同樣注意到倒數第二個位置的參數也被設置為false,這是為了去掉Stream開 始部分的多消息頭。

當調用CreateMtomWriter方法時,要加倍小心。兩個CreateMtomWriter方法 都使用MTOM 方式序列化和編碼XML Infosets,而第二個方法對於數據編碼提供 了更多的控制。明顯地,第二個方法有更大的好處,它允許我們對數據格式做更 多控制。肯定有程序需要這種級別的控制。如果接受者無法解釋消息,這種控制 就引入了阻斷互操作的可能性。正如你在第2章裡看到的一樣,使用MTOM一個主 要的動機就是互操作性,所以如果使用不當,就會違背使用MTOM的初衷。

CreateBinaryWriter  XmlDictionaryWriter也定義了4 個 CreateBinaryWriter方法。這些方法返回的是繼承自XmlDictionaryWriter能產 生二進制編碼的XML的實例。所有的方法都接受一個Stream參數。三個方法接受 一個XmlDictionary參數,兩個接受XmlBinaryWriterSession參數,一個也接受 Boolean參數。如果設定的話,XmlDictionary參數表示用於壓縮的 XmlDictionary對象。如果內有壓縮需求,可以傳遞 null參數。為了與 CreateTextWriter風格的統一,CreateBinaryWriter方法也有一個Boolean變量 ,它表示 XmlDictionaryWriter是否擁有Stream對象。

CreateBinaryWriter方法上的XmlBinaryWriterSession參數允許發送者和接 收者自動創建和協調一個動態的XmlDictionary。如前面提到的一樣,在使用之 前,key-value對必須添加到XmlDictionary對象。XmlDictionary內容必須在消 息參與者之間共享(典型的是在out-of-band機制中)。在消息參與者之間共享 XmlDictionary的內容是一個很大的挑戰,而XmlBinaryWriterSession應付了大 部分挑戰。在Stream 開始的時候,XmlBinaryWriterSession類型生成key-value 對,因此去掉了共享XmlDictionary的需求。內部來看, XmlBinaryWriterSession維持有自己的XmlDictionary,並且增加 XmlDictionaryString對象作為names、attribute names和XML namespaces在被 序列化的內容裡。XmlBinaryWriterSession產生數據不像通過XmlDictionary 和 二進制編碼序列化數據,但是XmlBinaryWriterSession不會強迫我們事先知道 XmlDictionary或者手動協調 XmlDictionary和接收者。為了在數據接收結束之 後解碼數據,接收者比如使用XmlBinaryReaderSession對象。 XmlBinaryReaderSession對象首先會自動從Stream對象初始化自身的數據信息。 作用上,XmlBinaryWriterSession類型動態創建和協調一個XmlDictionary對象 ,但是這樣也會有性能代價。

注釋:注意到在整個 XmlDictionaryWriter類型介紹裡這是第一次提到 XmlDictionary。正如所料,基於二進制編碼的XML是唯一合乎邏輯的語義壓縮方 式。 所有其他的方法都是設計來產生文本編碼的。從本性上說,UTF-8 和UTF- 16文本編碼是定義明確的,與二進制編碼壓縮的方式不同。也有一些別的定義清 晰的壓縮文本數據的機制(GZIP、霍夫曼編碼等等)。很有意思的一點是 XmlDictionaryWriter類型能夠處理多種編碼,但是目前只指定了一種二進制編 碼功能。

下面代碼展示了如何不使用XmlDictionary參數調用CreateBinaryWriter方法 。(你會在本章後面看到如何使用XmlDictionary。)

MemoryStream stream = new MemoryStream();
using (XmlDictionaryWriter writer =
     XmlDictionaryWriter.CreateBinaryWriter(stream, null,  null)) {
  writer.WriteStartDocument();
  writer.WriteElementString("SongName",
                             "urn:ContosoRockabilia",
                             "Aqualung");
  writer.Flush();
  Console.WriteLine(
     "XmlDictionaryWriter (Binary, no dictionary) wrote {0}  bytes",
     stream.Position);
  stream.Position = 0;

  Byte[] bytes = stream.ToArray();
  Console.WriteLine(BitConverter.ToString(bytes));
}

當代碼執行的時候,它會產生下面的結果:

XmlDictionaryWriter (Binary, no dictionary) wrote 43  bytes
3F-08-53-6F-6E-67-4E-61-6D-65-04-15-75-72-6E-3A-43-6F-6E-74-6F-73- 6F-52-6F-63-6B-61-62-69
6C-69-61-A1-08-41-71-75-61-6C-75-6E-67

Write方法

我們已經看過了不同創建XmlDictionaryWriter對象的方法,讓我們研究一下 如何使用這個對象寫XML。如前所述,XmlDictionaryWriter為把XML寫入Stream 對象定義了許多方法,這些方法名都以XmlWriter開始。 XmlDictionaryWriter 定義了幾個滿足消息應用需求的方法。為了避免重復敘述文檔,本章不會闡述 XmlDictionaryWriter 模仿XmlWriter的特性,而是關注在XmlDictionaryWriter 的新特性上:使用XmlDictionary對象。

使用XmlDictionary

許多XmlDictionaryWriter的寫方法包含XmlDictionaryString類型的參數。 這些方法基本都是成對出現,而且接受的都是String類型的參數。思考一下 XmlDictionaryWriter裡的2個方法原型:

// method accepting String objects
public void WriteElementString(String localName,
                                String ns,
                                String value);

// method accepting XmlDictionaryString and String objects
public void WriteElementString(XmlDictionaryString localName,
                                XmlDictionaryString namespaceUri,
                                String value);

注意到2個方法都包含3個參數,第二個方法為了局部name和namespace簡單地 接受2個XmlDictionaryString參數。重要的是知道第一個方法定義在XmlWriter 類型上,而第二個方法定義在XmlDictionaryWriter類型上。考慮到這些,你也 許想知道他們的區別。為了答案,我們要測試一下2個方法,然後比較結果。下 面的代碼使用接受三個String參數的WriteElementString方法:

private static void UseTextWriter() {
  MemoryStream stream = new MemoryStream();

  using (XmlDictionaryWriter writer =
       XmlDictionaryWriter.CreateTextWriter(stream,  Encoding.UTF8, true)) {
     writer.WriteElementString("SongName",
                               "urn:ContosoRockabilia",
                               "Aqualung");
     writer.Flush();
     Console.WriteLine("XmlDictionaryWriter (Text-UTF8) wrote  {0} bytes",
                       stream.Position);
     stream.Position = 0;
     Byte[] bytes = stream.ToArray();

     Console.WriteLine(BitConverter.ToString(bytes));
     Console.WriteLine("data read from stream:\n{0}\n",
       new StreamReader(stream).ReadToEnd());
  }
}

當代碼執行的時候,它會產生下面的結果:

XmlDictionaryWriter (Text-UTF8) wrote 59 bytes
3C-53-6F-6E-67-4E-61-6D-65-20-78-6D-6C-6E-73-3D-22-75-72-6E-3A-43- 6F-6E-74-6F-73-6F-52-6F
63-6B-61-62-69-6C-69-61-22-3E-41-71-75-61-6C-75-6E-67-3C-2F-53-6F- 6E-67-4E-61-6D-65-3E
data read from stream:
    <SongName  xmlns="urn:ContosoRockabilia">Aqualung</SongName>

下面運行一段相似的代碼,但是這次,調用接受XmlDictionaryString 參數 的WriteElementString方法:

private static void UseTextWriterWithDictionary() {
  MemoryStream stream = new MemoryStream();

  // build the dictionary and populate構建字典並填充字典
  XmlDictionary dictionary = new XmlDictionary();
  List<XmlDictionaryString> stringList = new  List<XmlDictionaryString>();
  stringList.Add(dictionary.Add("SongName"));
  stringList.Add(dictionary.Add("urn:ContosoRockabilia"));

  using (XmlDictionaryWriter writer =
       XmlDictionaryWriter.CreateTextWriter(stream,  Encoding.UTF8, true)) {
     writer.WriteElementString(stringList[0], stringList[1],  "Aqualung");
     writer.Flush();
     Console.WriteLine("XmlDictionaryWriter (Text-UTF8) wrote  {0} bytes",
                       stream.Position);
     stream.Position = 0;
     Byte[] bytes = stream.ToArray();

     Console.WriteLine(BitConverter.ToString(bytes));
     Console.WriteLine("data read from stream:\n{0}\n",
                       new StreamReader (stream).ReadToEnd());
  }
}

這些代碼會產生下面的結果

XmlDictionaryWriter (Text-UTF8) wrote 59 bytes
3C-53-6F-6E-67-4E-61-6D-65-20-78-6D-6C-6E-73-3D-22-75-72-6E-3A-43- 6F-6E-74-6F-73-6F-52-6F
63-6B-61-62-69-6C-69-61-22-3E-41-71-75-61-6C-75-6E-67-3C-2F-53-6F- 6E-67-4E-61-6D-65-3E
data read from stream:
<SongName  xmlns="urn:ContosoRockabilia">Aqualung</SongName>

2個方法產生相同的輸出結果!當使用XmlDictionary時,我們期望的依照語 法的壓縮沒有發生。如在XmlDictionaryWriter的討論裡說的一樣, XmlDictionary 只有在XmlDictionaryWriter產生二進制編碼的XML的時候才會有 用。但是對於產生二進制編碼XML的 XmlDictionaryWriter方法來說,使用 XmlDictionary是不受限制的。這個特性非常有用,為了弄個明白,思考一下下 面的方法:

// assume that stringList contains XmlDictionaryString  objects假設stringList包括XmlDictionaryString
// and is populated before this method is called並且已經填充 完畢
private static void WriteSomeXml(XmlDictionaryWriter writer)  {
  writer.WriteElementString(stringList[0], stringList[1],  "Aqualung");
}

WriteSomeXml接受任何繼承自XmlDictionaryWriter 類型的參數。包含生成 二進制編碼XML的XmlDictionaryWriter類型,也包括生成文本編碼XMl的類型。 由於 XmlDictionaryWriter編碼的靈活性,WriteSomeXml方法可以根據不同的編 碼來輸出XML數據。換句話說,可以接受 XmlDictionaryString參數的 WriteElementString的重載方法帶來的是一個靈活的API。

如果我們調用CreateBinaryWriter工廠方法創建一個XmlDictionaryWriter對 象,然後調用Write方法,我們會看到Stream裡一個完全不同的數據集。代碼演 示如下:

 // create the dictionary and add dictionary strings 創建字典並添加字符
  XmlDictionary dictionary = new XmlDictionary();
  List<XmlDictionaryString> stringList = new  List<XmlDictionaryString>();
  stringList.Add(dictionary.Add("SongName"));
  stringList.Add(dictionary.Add("urn:ContosoRockabilia"));
MemoryStream stream = new MemoryStream();
using (XmlDictionaryWriter writer =
     XmlDictionaryWriter.CreateBinaryWriter(stream, dictionary,  null)) {
  // write using the dictionary - element name, namespace,  value
  writer.WriteElementString(stringList[0], stringList[1],  "Aqualung");
  writer.Flush();
  Console.WriteLine("Using XmlDictionary w/Binary , wrote {0}  bytes",
                     stream.Position);
  stream.Position = 0;
  Byte[] bytes = stream.ToArray();
  Console.WriteLine(BitConverter.ToString(bytes));
}

當代碼執行的時候,它會產生下面的結果:

Using XmlDictionary w/Binary, wrote 14 bytes
42-00-0A-02-99-08-41-71-75-61-6C-75-6E-67

注意到XmlDictionary使用二進制編碼比文本編碼大小減少了75%(14 字節 vs. 59 字節)。在Stream裡,使用XmlDictionaryString整型key替換的string 的值,這一替換壓縮了數據的存儲空間。記住前面代碼裡對元素name(SongName) 和 namespace (urn:ContosoRockabilia)的替換。在此強調一下這一點,下面代 碼演示了如何不使用XmlDictionary實例直接生成二進制XML數據:

private static void UseBinaryWriter() {
  MemoryStream stream = new MemoryStream();
  using (XmlDictionaryWriter writer =
       XmlDictionaryWriter.CreateBinaryWriter(stream, null,  null)) {
     writer.WriteElementString("SongName",
                               "urn:ContosoRockabilia",
                               "Aqualung");
     writer.Flush();
     Console.WriteLine("Not Using XmlDictionary w/Binary,  wrote {0} bytes",
                       stream.Position);
     stream.Position = 0;
     Byte[] bytes = stream.ToArray();
     Console.WriteLine(BitConverter.ToString(bytes));
  }
}

當代碼執行的時候,它會產生下面的結果:

Not Using XmlDictionary w/Binary, wrote 43 bytes
3F-08-53-6F-6E-67-4E-61-6D-65-04-15-75-72-6E-3A-43-6F-6E-74-6F-73- 6F-52-6F-63-6B-61-62-69
6C-69-61-A1-08-41-71-75-61-6C-75-6E-67

在我們的測試裡, 與不使用XmlDictionary的二進制編碼相比,使用 XmlDictionary的二進制編碼減少了67%的大小。進一步了解XmlDictionary和 XmlDictionaryWriter的目的,讓我們再看一下使用文本編碼、二進制編碼在不 使用和使用dictionary時候的字節順序,

XML to be encoded:
<SongName  xmlns="urn:ContosoRockabilia">Aqualung</SongName>
XmlDictionaryWriter (Text-UTF8) wrote 59 bytes
3C-53-6F-6E-67-4E-61-6D-65-20-78-6D-6C-6E-73-3D-22-75-72-6E-3A-43- 6F-6E-74-6F-73-6F-52-6F
63-6B-61-62-69-6C-69-61-22-3E-41-71-75-61-6C-75-6E-67-3C-2F-53-6F- 6E-67-4E-61-6D-65-3E
XmlDictionaryWriter (binary) No XmlDictionary wrote 43  bytes
3F-08-53-6F-6E-67-4E-61-6D-65-04-15-75-72-6E-3A-43-6F-6E-74-6F-73- 6F-52-6F-63-6B-61-62-69
6C-69-61-A1-08-41-71-75-61-6C-75-6E-67

XmlDictionaryWriter (binary), With XmlDictionary wrote 14  bytes
41-00-06-02-A1-08-41-71-75-61-6C-75-6E-67

注意黑體的字節順序。如果我們把這些字節轉換為ASCII字符,我們會看到下 面的ASCII-到-byte的轉換:

SongName
53-6F-6E-67-4E-61-6D-65
urn:ContosoRockabilia
75-72-6E-3A-43-6F-6E-74-6F-73-6F-52-6F-63-6B-61-62-69-6C-69-61
Aqualung
41-71-75-61-6C-75-6E-67

基於前面的例子,我們知道產生二進制編碼XML的XmlDictionaryWriter不使 用XmlDictionary來直接編寫元素name、XML namespaces、attribute values和 element values到Stream。當然XmlDictionaryWriter也可以使用XmlDictionary 實例來生成帶有原書和屬性值的二進制編碼的XML數據,但是會在Stream裡為元 素name和XML namespaces替換掉單個字節。

注釋:我的看法,這種壓縮的有很大的好處。在分布式計算力,性能的一個 主要方面就是傳輸數據的大小。通常來說,更小數據傳輸會帶來高效率的系統。 把這個與消息應用關聯起來,就是更小的消息意味著更小的數據傳輸,也就意味 著更高的應用程序效率。代表性地,開發者和架構師過去經常考慮文本編碼的 XML,SOAP消息依賴數據傳輸因此性能很差。使用WCF以後,就會產生更緊湊的 XML數據,很重要的是要指出討論過二進制編碼是不存在的,因為WCF可以產生很 緊湊的XML數據。另外要重點指出的是討論過的二進制編碼不會與其它平台交互 。希望日後,行業可以采納標准的二進制編碼。

現在我們已經看了如何實例化一個XmlDictionaryWriter對象並寫XML數據到 Stream裡,那麼我們再來看一下如何使用XmlDictionaryReader從Stream讀取XML 數據。

【老徐備注】

1. Big Endian和Little Endian:

在設計計算機系統的時候,有兩種處理內存中數據的方法。一種叫為little -endian,存放在內存中最低位的數值是來自數據的最右邊部分(也就是數據的 最低位部分)。另一種稱為big-endian,正好相反,存放在內存中最低位的數值 是來自數據的最左邊邊部分(也就是數據的最高為部分)。

2. XmlDictionary:

實現用於優化 Windows Communication Foundation (WCF) 的 XML 讀取器/ 編寫器實現的字典。

字典在常見文本字符串和整數之間建立映射,並為壓縮和解壓縮 XML 提供一 種有效的機制。Windows Communication Foundation (WCF) 使用靜態和動態 2 種字典。

使用靜態字典時,通信的兩端都使用預定義的字典。

使用動態字典時,發送端可以添加其映射不在靜態字典中的新字符串。動態 字典與消息一起在帶外發送。動態字典使用 XmlBinaryWriterSession 和 XmlBinaryReaderSession 類傳輸消息和映射。

參考:http://msdn.microsoft.com/zh- cn/library/system.xml.xmldictionary.aspx

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