首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WCF 底層異常處理框架深度剖析:FaultFormatter 建立與序列化機制全揭秘(下)

     編輯:關於.NET

WCF 客戶端與服務端框架協作無間,讓開發人員如同本地呼叫般處理異常:服務端拋出 FaultException,客戶端捕獲處理,完全屏蔽了「分散式」的複雜性。為達成此體驗,WCF 內部完成了大量幕後工作。

訊息交換是 WCF 通信唯一手段,異常、中繼資料均以訊息形式傳遞。實現異常與訊息雙向轉換是異常處理體系核心,WCF 異常處理框架專職於此。簡述流程:服務端將 FaultException 序列化,依 SOAP 與 WS-Addressing 規格生成 Fault 訊息,經通道層傳輸返回客戶端;客戶端接收後反序列化重建 FaultException 並拋出。此過程中引入 MessageFault 作為中介物件,圖示如右。

一、FaultFormatter 如何被建立?

服務端與客戶端各需一個 FaultFormatter,分別負責序列化與反序列化。兩端建立方式相似,均基於錯誤描述。

1. 服務端:DispatchFaultFormatter 的誕生

ServiceHost 初始化時,為每個端點建立 EndpointDispatcher,各持有 DispatchRuntime。DispatchRuntime 是運行時核心,引用眾多物件控制訊息分發與操作執行。初始化過程中,根據契約描述(ContractDescription)遍歷操作描述(OperationDescription)建立 DispatchOperation。三者關係如下:

public class ServiceEndpoint { public ContractDescription Contract { get; } }
public class ContractDescription { public OperationDescriptionCollection Operations { get; } }
public class OperationDescription { public FaultDescriptionCollection Faults { get; } }

OperationDescription.Faults 集合元素為 FaultDescription,對應操作上標註的 FaultContractAttribute。建立 DispatchOperation 時,根據錯誤描述建立 FaultFormatter(型別 IDispatchFaultFormatter):

public sealed class DispatchOperation
{
    public SynchronizedCollection<FaultContractInfo> FaultContractInfos { get; }
    internal IDispatchFaultFormatter FaultFormatter { get; set; }
}

FaultContractInfo 僅含錯誤明細型別與 Action,用於序列化時確定型別與 Action 報頭:

public class FaultContractInfo { public string Action { get; } public Type Detail { get; } }

序列化需先確定錯誤明細型別。MessageFault 無 Action 屬性,但 SOAP 訊息必須有 WS-Addressing Action 報頭。WCF 規則:優先用 FaultException 自身 Action;否則從 FaultContractInfo 尋找匹配型別的 Action;再無則依 WS-Addressing 版本用預設值:

  • WS-Addressing 2004: https://www.w3.org/2005/08/addressing/soap/fault
  • WS-Addressing 1.0: https://schemas.xmlsoap.org/ws/2004/08/addressing/fault

FaultFormatter 建構函式接受 FaultContractInfo 集合:

internal class FaultFormatter : IClientFaultFormatter, IDispatchFaultFormatter
{
    internal FaultFormatter(Type[] detailTypes);
    internal FaultFormatter(SynchronizedCollection<FaultContractInfo> faultContractInfoCollection);
}

2. 客戶端:ClientFaultFormatter 的建立

客戶端透過 ChannelFactory<TChannel> 建立代理,端點隨之建立。ClientRuntime 初始化時為每個操作建立 ClientOperation,同樣擁有 FaultContractInfos 與 FaultFormatter(型別 IClientFaultFormatter)。

3. DataContractSerializerFaultFormatter vs XmlSerializerFaultFormatter

WCF 提供兩種 FaultFormatter,分別使用 DataContractSerializer 與 XmlSerializer。預設採惰性載入建立 DataContractSerializerFaultFormatter。若需使用 XmlSerializer,可在契約、型別或操作上套用 XmlSerializerFormatAttribute,內部由 XmlSerializerOperationBehavior 實作,在 ApplyClientBehavior/ApplyDispatchBehavior 中替換為 XmlSerializerFaultFormatter。

public class XmlSerializerOperationBehavior : IOperationBehavior, IWsdlExportExtension
{
    void IOperationBehavior.ApplyClientBehavior(OperationDescription description, ClientOperation proxy)
    { proxy.FaultFormatter = this.CreateXmlSerializerFaultFormatter(); }
    void IOperationBehavior.ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch)
    { dispatch.FaultFormatter = this.CreateXmlSerializerFaultFormatter(); }
}

二、異常拋出、序列化、反序列化與捕獲全流程

服務操作由 DispatchOperation.OperationInvoker 執行。若拋出 FaultException,WCF 取得 DispatchOperation.FaultFormatter,呼叫 Serialize 獲取 MessageFault 與 Action,再透過 Message.CreateMessage 生成 Fault 訊息。

客戶端調用由 ClientOperation 完成。收到回覆訊息若為 Fault,轉為 MessageFault 取得 Action,再由 ClientOperation.FaultFormatter.Deserialize 反序列化重建 FaultException 並拋出。開發者感知如同本地異常傳遞。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved