本文透過模擬 ServiceMetadataBehavior,示範如何基於 WS-MEX 協定發布服務元資料。核心在於自訂服務行為 ServiceMetadataBehaviorAttribute,在 ApplyDispatchBehavior 中完成兩件事:導出元資料、自訂 MEX 端點的 DispatchRuntime。
Utility.CreateInstance、Utility.SetPropertyValue 以反射建立 internal 型別、設定非公屬性。IMetadataProvisionService(對應 IMetadataExchange),定義 Get(Message) 操作,Action/ReplyAction 依 WS-Transfer 規範。MetadataMessage 以 MessageBodyMember 包裝 MetadataSet,符合 WS-MEX 訊息結構。MetadataProvisionService 實作 IMetadataProvisionService,將 MetadataSet 轉為 Message 回傳。ServiceMetadataBehaviorAttribute 實作 IServiceBehavior,ApplyDispatchBehavior 中:
GetExportedMetadata 透過 WsdlExporter 導出元資料(過濾掉 MEX 端點本身)。CustomizeMexEndpoints 遍歷 ChannelDispatcher 下的 EndpointDispatcher,找出 MEX 端點(依契約名稱/命名空間),將其 DispatchRuntime.InstanceContextProvider 設為 SingletonInstanceContextProvider,並建立封裝 MetadataProvisionService 的 SingletonInstanceContext。private static void CustomizeMexEndpoints(ServiceDescription description, ServiceHostBase host, MetadataSet metadata)
{
foreach (ChannelDispatcher channelDispatcher in host.ChannelDispatchers)
{
foreach (EndpointDispatcher endpoint in channelDispatcher.Endpoints)
{
if (endpoint.ContractName == MexContractName && endpoint.ContractNamespace == MexContractNamespace)
{
DispatchRuntime dispatchRuntime = endpoint.DispatchRuntime;
dispatchRuntime.InstanceContextProvider = Utility.CreateInstance<IInstanceContextProvider>(SingletonInstanceContextProviderType, new Type[] { typeof(DispatchRuntime) }, new object[] { dispatchRuntime });
MetadataProvisionService serviceInstance = new MetadataProvisionService(metadata);
dispatchRuntime.SingletonInstanceContext = new InstanceContext(host, serviceInstance);
}
}
}
}
服務類別套用 [ServiceMetadataBehavior],組態加入 MEX 端點(契約為自訂 IMetadataProvisionService)。客戶端同樣以 ChannelFactory<IMetadataProvisionService> 呼叫 Get 取得元資料,寫入 XML 檔並以 IE 開啟(圖 2)。

圖 2 獲取的元資料在 IE 中的顯示