前言:
在WCF初探-5:WCF消息交換模式之雙工通訊(Duplex)博文中,我講解了雙工通信服務的一個應用場景,即訂閱和發布模式,這一篇,我將通過一個消息發送的例子講解一下WCF客戶端如何為雙工服務創建回調對象。
雙工服務指定一個回調協定,客戶端應用程序必須實現該協定以便提供一個該服務能夠根據協定要求調用的回調對象。雖然回調對象不是完整的服務(例如,您無法使用回調對象啟動一個通道),但是為了實現和配置,這些回調對象可以被視為一種服務。
雙工服務的客戶端必須:
- 實現一個回調協定類。
- 創建回調協定實現類的一個實例,並使用該實例創建傳遞給 WCF 客戶端構造函數的 System.ServiceModel.InstanceContext 對象。
- 調用操作並處理操作回調。
雙工 WCF 客戶端對象除了會公開支持回調所必需的功能(包括回調服務的配置)以外,其他的功能和它們的非雙工對應項相同。
示例說明:
- Service服務契約中定義了一個發送方法Send,采用IsOneWay=true,供客戶端調用,向服務端發送消息。Service中還提供了用於雙工通信的回調接口IMessageExchangeCallback,該接口中定義了服務端接收消息后向客戶端發送消息的方法Receive,此方法就是客戶端發送消息到服務端后,服務端調用回調方法,將消息發送到客戶端。
- Client需要實現雙工協定回調接口的類CallBackHandler,並實現Receive方法。
- 針對雙工協定生成的 WCF 客戶端需要在構造時提供一個 InstanceContext 類。此 InstanceContext 類用作實現回調接口並處理從服務發送回的消息的對象所在的位置。InstanceContext 類是用 CallbackHandler 類的實例構造的。此對象處理通過回調接口從服務發送到客戶端的消息。
WCF客戶端為雙工服務創建回調對象示例:
- 解決方案如下:
- 工程結構說明:
- Service:類庫程序,定義服務契約接口和回調接口,實現服務契約。在IMessageExchange中定義了Send方法,並且還定義了雙工服務回調接口 IMessageExchangeCallback。
IMessageExchange.cs的代碼如下:
using System.ServiceModel; using System.Collections.Generic; using System.Runtime.Serialization; namespace Service { [ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IMessageExchangeCallback))] public interface IMessageExchange { [OperationContract(IsOneWay=true)] void Send(string message); } public interface IMessageExchangeCallback { [OperationContract(IsOneWay = true)] void Receive(string message); } }
MessageExchange.cs的代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; namespace Service { [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)] public class MessageExchange : IMessageExchange { public void Send(string message) { Console.WriteLine("服務端監聽客戶端發出的消息:" + message); Callback.Receive(message); } IMessageExchangeCallback Callback { get { return OperationContext.Current.GetCallbackChannel<IMessageExchangeCallback>(); } } } }
注意:回調契約接口IMessageExchangeCallback中的Receive方法是在客戶端實現的,所以如果需要在服務端調用回調方法就必須通過當前操作的實例上下文來獲取,即上面代碼中的Callback對象。
2. Host:控制台應用程序。提供服務寄宿程序,添加對Srevice程序集的引用。完成配置文件和代碼就可以承載服務。
Program.cs的代碼如下:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Service; using System.ServiceModel; namespace Host { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(MessageExchange))) { host.Opened += delegate { Console.WriteLine("服務已經啟動,按任意鍵終止!"); }; host.Open(); Console.Read(); } } } }
App.config的代碼如下:

<?xml version="1.0"?> <configuration> <system.serviceModel> <services> <service name="Service.MessageExchange" behaviorConfiguration="mexBehavior"> <host> <baseAddresses> <add baseAddress="http://localhost:1234/MessageExchange/"/> </baseAddresses> </host> <endpoint address="" binding="wsDualHttpBinding" contract="Service.IMessageExchange" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="mexBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
3. Client:控制台應用程序。客戶端程序,啟動服務承載程序Host后,添加對服務地址http://localhost:1234/MessageExchange/的引用,將命名空間修改為
MessageExchangeServiceRef,之后在Program.cs完成對雙工服務回調接口IMessageExchangeCallback的實現和對服務方法的調用。Program.cs的代碼如下:
using System; using Client.MessageExchangeServiceRef; using System.ServiceModel; namespace Client1 { public class CallBackHandler : IMessageExchangeCallback { public void Receive(string message) { Console.WriteLine("客戶端監聽服務端接收的消息:" + message); } } class Program { static void Main(string[] args) { InstanceContext instanceContext = new InstanceContext(new CallBackHandler()); MessageExchangeClient proxy = new MessageExchangeClient(instanceContext); proxy.Send("Wcf Duplex"); Console.Read(); } } }
運行結果如下:
總結:
- 本文模擬了客戶端向服務端發送消息,服務端接收到消息后,將監聽到的消息顯示在客戶端。希望通過本示例對雙工通信有進步一的認識,關於實例和會話,我將在后面的博文中做解析。