上篇介紹了訊息版本與五種建立方式,本文深入探討 Message 物件的狀態機與四大基本操作:讀、寫、拷貝、關閉。理解狀態轉換規則,是避免運行時異常、正確實作訊息檢查與記錄的基石。
MessageState 列舉定義五種狀態:Created、Read、Written、Copied、Closed。核心規則:
Created 狀態可執行讀、寫、拷貝操作Read;寫操作 → Written;拷貝 → CopiedClose(),轉為 Closed
最常用 GetBody<T>() 反序列化 Body 為強型別物件,或用 GetReaderAtBodyContents() 取得 XmlDictionaryReader 手動解析。
範例: 序列化 Customer 資料契約為訊息,再 GetBody<Customer>() 還原,驗證 Equals 為 true。
狀態限制實測: 首次讀取後狀態變 Read,再次呼叫 GetBody<T>() 將拋出 InvalidOperationException。
message.State = Read // 第二次 GetBody 拋出異常

Message 提供 WriteMessage、WriteBody、WriteBodyContents、WriteStartEnvelope 等方法,支援寫入 XmlWriter 或 XmlDictionaryWriter。寫入後狀態轉為 Written,同樣僅限 Created 狀態呼叫。
輔助方法 WriteMessage 示範將訊息存檔並開啟:
static void WriteMessage(Message msg, string file)
{
using (var writer = new XmlTextWriter(file, Encoding.UTF8))
msg.WriteMessage(writer);
Process.Start(file);
}
實際 WCF 管線中,訊息常需同時被記錄(寫入日誌)與處理(反序列化)。直接讀寫會改變狀態導致後續失效。解決方案:CreateBufferedCopy(maxBufferSize) 產生 MessageBuffer(記憶體緩衝),原訊息狀態轉 Copied;再透過 buffer.CreateMessage() 產生新訊息(狀態 Created),可重複讀寫。
var buffer = msg.CreateBufferedCopy(int.MaxValue); msg = buffer.CreateMessage(); // 新訊息,可讀 var c1 = msg.GetBody<Customer>(); msg = buffer.CreateMessage(); // 另一新訊息,可再讀 var c2 = msg.GetBody<Customer>(); // 成功,無異常
此機制是 WCF 訊息檢查器、記錄擴展正常運作的基礎。