前言
- 在上一篇WCF中使用Message類(上)中,文章介紹了WCF中使用Message類的基本知識和怎樣創建消息,本文是承接上一篇文章,如果想要更好的閱讀本文,請先閱讀上一篇文章。在這篇文章中,我將介紹怎樣來操作消息。
- 從WCF中使用Message類(上)中,我們知道了消息的基本結構,針對不同的情況,我們對消息進行了創建。在創建消息后,我們還可以對消息進行寫入、讀取、復制等操作,以便我們在不同的任務環境下更好的運用消息傳輸機制。
通過Message類提取消息正文的幾種方式
- Message 類支持多種從其正文提取信息的方式。它們可分為以下幾類:
- 將整個消息正文一次性寫出到 XML 編寫器。這稱為“寫入消息”。
- 將 XML 讀取器放在消息正文上。這使您可以在以后根據需要逐段訪問消息正文。這稱為“讀取消息”。
- 可以將整個消息(包括它的正文)復制到類型為 MessageBuffer 的內存中緩沖區。這稱為“復制消息”。
- 注意:無論使用哪種訪問方式,都只能訪問 Message 的正文一次。消息對象具有 State 屬性,該屬性最初設置為 Created。前面列表中描述的三種訪問方法分別將狀態設置為 Written、Read 和 Copied。此外,Close 方法可以在不再需要消息正文內容時將狀態設置為 Closed。只有當消息正文處於 Created 狀態時,才能對其進行訪問,並且在狀態已更改后,無法返回到 Created 狀態。
寫入消息
- Message類為我們提供了幾種寫入消息的方法
- WriteBodyContents 方法:將給定 Message 實例的正文內容寫出到給定 XML 編寫器
- WriteBody 方法:執行相同的操作,不同之處在於該方法將正文內容封裝在適當的包裝元素(如 <soap:body>)中。
- WriteMessage方法:寫出整個消息,包括 SOAP 包裝信封和標頭。如果禁用 SOAP(Version 為 MessageVersion.None),則所有這三個方法都執行相同的操作:寫出消息正文內容。
- 注意:本文采用的示例為WCF中使用Message類(上)中所使用的示例,源碼已經在文章底部的評論區給出,下載后,我們可以根據本文的操作完善代碼,驗證我們對消息的操作。本文的源碼也已經在文章底部的評論區給出。
- 我們可以分別采用Message類不同的操作方法類寫入消息結構。參考代碼如下:
//寫入消息 Message message = proxy.GetDataXml(); FileStream stream = new FileStream(@"c:/log.xml", FileMode.Create); XmlDictionaryWriter xdr = XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8); message.WriteBodyContents(xdr); //message.WriteBody(xdr); //message.WriteMessage(xdr); xdr.Flush(); Console.WriteLine("消息寫入成功");
- 使用WriteBodyContents寫入消息結構,寫入后我們可以看到log.xml的文件結構如下:

2. 使用WriteBody寫入消息結構,寫入后我們可以看到log.xml的文件結構如下:

3. 使用WriteMessage寫入消息結構,寫入后我們可以看到log.xml的文件結構如下

讀取消息
- 讀取消息正文的主要方式是調用 GetReaderAtBodyContents。您會取回一個 XmlDictionaryReader 以便用於讀取消息正文。請注意,只要調用了 GetReaderAtBodyContents,Message 就會轉換到 Read 狀態,而不是在您使用返回的 XML 讀取器時發生轉換。
- 使用 GetBody 方法還可以將消息正文作為類型化對象進行訪問。在內部,此方法使用 GetReaderAtBodyContents,因而也會將消息狀態轉換為 Read 狀態。
- 接下來,我將使用GetBody來讀取從對象中創建的消息,參考代碼如下:
//讀取消息 Message message = proxy.GetDataObject(); User user = message.GetBody<User>(); Console.WriteLine("讀取消息信息成功"); Console.WriteLine(user.ID+"->"+user.Name);
運行結果顯示如下:

將消息復制到緩沖區中
- 要使整個消息緩存到內存中,可以通過調用 CreateBufferedCopy 達到此目的。此方法采用一個表示最大緩沖區大小的整型參數,且創建一個不大於此大小的緩沖區。
- 緩沖區作為一個 MessageBuffer 實例返回。可以通過幾種方式訪問緩沖區中的數據。主要方式是調用 CreateMessage 以便從緩沖區創建 Message 實例。
- 訪問消息緩沖區內容的方式是使用 WriteMessage 將緩沖區的內容寫出到流中。
- 接下來,我們通過使用CreateBufferedCopy來創建消息緩存區,並使用WriteMessage將消息寫入到log.xml文件中,參考代碼如下:
//復制消息 Message message = proxy.GetDataXml(); MessageBuffer mb = message.CreateBufferedCopy(65536); FileStream stream = new FileStream(@"c:/log.xml", FileMode.Create); mb.WriteMessage(stream); stream.Flush(); Console.WriteLine("復制消息信息成功");
運行后,log.xml文件結構如下:

訪問其他消息部分
- Headers 屬性表示消息頭。可以通過類型為 MessageHeaders 的 Headers 屬性來訪問標頭。MessageHeaders 是一個 MessageHeaderInfo 對象集合,可以通過其 IEnumerable 接口或其索引器來訪問各個標頭。
- Properties 屬性表示消息屬性,這些屬性是附加到消息的命名數據段,且通常不會在發送消息時發出。請參見本主題稍后關於“使用屬性”的部分。
- Version 屬性指示與消息相關聯的 SOAP 和 WS-Addressing 版本;如果禁用了 SOAP,則該屬性為 None。
- IsFault 屬性在消息為 SOAP 錯誤消息時返回 true。
- IsEmpty 屬性在消息為空時返回 true。
- 接下來,我們將通過Message的實例輸出其屬性,參考代碼如下:
//訪問消息的其他部分 Message message = proxy.GetDataEmpty(); Console.WriteLine("Version:" + message.Version.ToString()); Console.WriteLine("State:" + message.State.ToString()); Console.WriteLine("IsEmpty:" + message.IsEmpty.ToString()); Console.WriteLine("IsFault:" + message.IsFault.ToString()); Console.WriteLine("消息Headers包含的屬性如下:"); foreach (MessageHeaderInfo item in message.Headers) { Console.WriteLine(item.Name); }
運行結果如下:

