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

《WCF技術內幕》23

編輯:關於.NET

《WCF技術內幕》23:第2部分_第5章_消息:XmlDictionaryReader和回到Message

XmlDictionaryReader類型

XmlDictionaryReader抽象類型繼承自System.Xml.XmlReader,因此繼承了很 多XmlReader的特性。和XmlReader 一樣,XmlDictionaryReader定義了幾個工廠 方法,他們返回的是XmlDictionaryReader的子類型的實例。更確切地說, XmlDictionaryReader包裝了一個Stream,並定義了許多以Read開頭的方法。因 此,由於繼承的層次關系,使用 XmlDictionaryReader和XmlReader很相似。

和XmlReader不同,XmlDictionaryReader的目的是為了讀取序列化的和編碼 過的XML Infosets ,並且可以由選擇地借助XmlDictionary來實現語義壓縮的反 向處理。作用上,XmlDictionaryReader 和XmlDictionaryWriter正好相反,並 且2個類型的對象模型非常相似。讓我們從XmlDictionaryReader的創建方法開始 學習,然後詳細研究如何使用它的Read方法。因為XmlDictionaryReader和 XmlDictionaryWriter的相似性,本節會比上一節XmlDictionaryWriter要簡短一 些。

創建一個XmlDictionaryReader對象

XmlDictionaryReader類型定義了幾個工廠方法,所有這些方法都直接或者間 接地,接受一個Stream 或Byte[]的引用。通常來說,面向stream的方法與面向 buffer的方法很相似。絕大部分,這些工廠方法都是重載一下4個方法: CreateDictionaryReader, CreateTextReader, CreateMtomReader和 CreateBinaryReader,它們的行為與XmlDictionaryWriter的相同名字工廠方法 對應。為了避免重復,我們將會關注XmlDictionaryReader的工廠方法的顯著特 性上。

幾個工廠方法接受一個Stream的引用,這些面向stream的工廠方法使用的其 它參數包含一個XmlDictionaryQuotas 對象的引用和一個 OnXmlDictionaryReaderClose委托。在所有的情況下,前者調用後者,為 XmlDictionaryQuotas 和OnXmlDictionaryReaderClose參數傳遞null引用。

XmlDictionaryQuotas類型是一個狀態容器,它用來定義與XML反序列化相關 的重要的閥值。例如,這個類型定義反序列化中用到的節點深度的最大值、反序 列化最大的String長度、消息體的最大數組長度等等【老徐備注1】。

OnXmlDictionaryReaderClose委托在XmlDictionaryReader 的Close方法幾乎 結束的時候調用。當這個委托被激活以後,XmlDictionaryReader的大部分狀態 被設置為null。因此,這個委托可以用來作為提醒機制(很像一個事件event) ,但不會提供XmlDictionaryReader狀態相關的任何有價值的信息(除非Null是 有價值的)。Message編碼器使用OnXmlDictionaryReaderClose委托去把 XmlDictionaryReader對象放到對象池。這些編碼器依賴 OnXmlDictionaryReaderClose委托這樣的提醒,它會返回一個資源池裡的 XmlDictionaryReader實例。

一下代碼演示了如何實例化一個XmlDictionaryReader對象:

private static void CreateTextReader() {
  Console.WriteLine("==== Creating XML Dictionary Text  Reader ====");
  MemoryStream stream = new MemoryStream();

  // create an XmlDictionaryWriter and serialize/encode some  XML
  XmlDictionaryWriter writer =  XmlDictionaryWriter.CreateTextWriter(stream,
     Encoding.BigEndianUnicode, false);
  writer.WriteStartDocument();
     writer.WriteElementString("SongName",
                               "urn:ContosoRockabilia",
                               "Aqualung");
  writer.Flush();
  stream.Position = 0;

  // create an XmlDictionaryReader to decode/deserialize the  XML
  XmlDictionaryReader reader =  XmlDictionaryReader.CreateTextReader(
     stream, Encoding.BigEndianUnicode, new  XmlDictionaryReaderQuotas(),
     delegate { Console.WriteLine("closing reader"); }  );
  reader.MoveToContent();
  Console.WriteLine("Read XML Content:{0}",reader.ReadOuterXml ());

  Console.WriteLine("about to call reader.Close()");
  reader.Close();
  Console.WriteLine("reader closed");
}

當以上代碼執行的時候,就會產生以下輸出:

==== Creating XML Dictionary Text Reader ====
Read XML Content:
<SongName  xmlns="urn:ContosoRockabilia">Aqualung</SongName>
about to call reader.Close()
closing reader
reader closed

著重指出一下,XmlDictionaryReader的其它工廠方法接受的參數和 XmlDictionaryWriter的工廠方法幾乎一一對應。這些參數與在 XmlDictionaryWriter類型裡的作用一樣。

借助XmlDictionary生成XML數據

既然已經看了如何實例化XmlDictionaryWriter和XmlDictionaryReader,現 在我們就學習一下如何使用XmlDictionary讀取二進制編碼的XML。如下面的代碼 所示,這與你在XmlDictionaryWriter裡看到的一樣:

MemoryStream stream = new MemoryStream();
// 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"));

// use an XmlDictionaryWriter to serialize some XML使用 XmlDictionaryWriter序列化一些XMl
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 Dictionary, wrote {0} bytes",
                     stream.Position);
  stream.Position = 0;
  Byte[] bytes = stream.ToArray();
  Console.WriteLine(BitConverter.ToString(bytes));

  // create an XmlDictionaryReader passing the Stream創建 XmlDictionaryReader並傳遞Stream
  // and an XmlDictionary
  XmlDictionaryReader reader =
     XmlDictionaryReader.CreateBinaryReader(stream, dictionary,  new
       XmlDictionaryReaderQuotas());
  reader.Read();
  Console.WriteLine("data read from stream:\n{0}\n",
     reader.ReadOuterXml());
}

當代碼執行的時,輸出一下結果:

XmlDictionaryWriter (Binary w/dictionary) wrote 14  bytes
42-00-0A-02-99-08-41-71-75-61-6C-75-6E-67
data read from stream:
<SongName  xmlns="urn:ContosoRockabilia">Aqualung</SongName>

注意到傳遞到CreateBinaryWriter方法上的XmlDictionary和傳遞到 XmlDictionaryReader方法上的XmlDictionary是一個對象的引用。誠然,傳遞同 一個對象的引用的是有些粗糙但是能保證XmlDictionaryWriter 和 XmlDictionaryReader使用一個詞匯表,但是它說明了XmlDictionaryReader可以 解釋XmlDictionaryWriter使用XmlDictionary壓縮的數據。

回到Message類型

既然我們已經研究過了序列化和編碼一個Message的相關類型,現在該重新關 注一下Message類型了。Message對象模型初略估計包含45個public或protected 的成員。這些成員中包含返回Message實例的工廠方法、序列化Message的方法、 反序列化Message的方法、返回Message信息的屬性、處理Message頭部的屬性和 清理Message的方法。

【老徐備注】

1.為交換的 Soap 消息指定復雜性約束的 XmlDictionaryReaderQuotas。下 面的備注部分中提供了這些約束的默認值。

這些復雜性約束可以抵御某種類型的拒絕服務 (DOS) 攻擊,這些攻擊試圖利 用消息復雜性來占用終結點處理資源。表達這些約束及其默認值的屬性如下所示 :

字典讀取器最重要的安全功能是配額。必須為字典讀取器工廠方法指定配額 實例。默認構造函數創建“安全”默認值(與編碼默認值相同),並且類具有靜 態 Max 屬性,用於創建不帶配額的讀取器。

5.maxDepth="32" 最大節點深度

6.maxStringContentLength="8192" 最大內容長度

7.maxArrayLength="16384"最大數組長度

8.maxBytesPerRead="4096" 最大每次讀取長度

9.maxNameTableCharCount="16384"最大NameTableChar的數量

我曾經在MSDN WCF中文論壇解釋過,WCF使用到的所有的Max的作用。

http://social.microsoft.com/Forums/zh-CN/wcfzhchs/thread/73f31b97- bef5-47c6-b50e-d0d3140d8efb

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