WCF 架構龐大,組件眾多。與其死記組件名稱,不如親手用 ASP.NET 搭建一個迷你 WCF 框架,體驗訊息編碼、序列化、調度、調用的完整流程。本文將引導你從零實作 Client/Server 核心管道,深度理解 WCF 內部運作。
| 階段 | 服務端組件 | 客戶端組件 |
|---|---|---|
| 傳輸收發 | Channel Stack (Listener) | Channel Stack (Request/Reply) |
| 編碼/解碼 | MessageEncoder / MessageEncoderFactory | MessageEncoder / MessageEncoderFactory |
| 序列化/反序列化 | IDispatchMessageFormatter | IClientMessageFormatter |
| 實例管理 | IInstanceProvider | — |
| 操作調用 | IOperationInvoker | — |
ICalculator (Class Library)。Calculator.aspx 模擬服務端管道。RealProxy 模擬代理調用。WCF 內部組件 (TextMessageEncoderFactory、DataContractSerializerOperationFormatter、SyncMethodInvoker) 皆為 internal,必須用反射建立:
public static void Create<T>(
out MessageEncoderFactory encoderFactory,
out IDictionary<string, IClientMessageFormatter> clientFormatters,
out IDictionary<string, IDispatchMessageFormatter> dispatchFormatters,
out IDictionary<string, IOperationInvoker> operationInvokers,
out IDictionary<string, MethodInfo> methods)
{
// 1. 驗證 ServiceContractAttribute
// 2. 反射建立 TextMessageEncoderFactory
// 3. 解析 OperationContractAttribute 取得 Action、Name
// 4. 反射建立 DataContractSerializerOperationFormatter (雙介面)
// 5. 反射建立 SyncMethodInvoker
// 6. 填入字典:Key = OperationName (Formatter) / Action (Invoker/MethodInfo)
}
protected void Page_Load(object sender, EventArgs e)
{
// 1. Encoder.ReadMessage(Request.InputStream) → Request Message
// 2. Request.Headers.Action → 找到 MethodInfo
// 3. DispatchFormatter.DeserializeRequest → 參數陣列
// 4. Activator.CreateInstance(ServiceType) → 服務實例 (簡化版 InstanceProvider)
// 5. OperationInvoker.Invoke(instance, params, out outParams) → 執行操作
// 6. DispatchFormatter.SerializeReply → Reply Message
// 7. Encoder.WriteMessage(Reply, Response.OutputStream) → 回應客戶端
}
RealProxy,覆寫 Invoke(IMessage)。IMethodCallMessage 取得方法名、參數。ClientFormatter.SerializeRequest → Request Message。Encoder.WriteMessage → 位元組陣列 → HttpWebRequest.Post 發送。HttpWebResponse → Encoder.ReadMessage → Reply Message。ClientFormatter.DeserializeReply → 返回值 + ref/out 參數映射回 ReturnMessage。// Client 程式
var calculator = ServiceProxyFactory<ICalculator>.Create(
MessageVersion.Default,
new Uri("https://localhost/.../Calculator.aspx"));
double result = calculator.Add(1, 2); // 輸出: 3
Message 流轉,編碼/序列化/調度皆為訊息轉換。IInstanceProvider、IOperationInvoker、MessageFormatter、MessageEncoder 皆可自訂替換。親手搭建迷你框架,WCF 不再是黑盒,而是清晰可控的管道組合。