所謂WCF的雙工服務,指的就是說,在WCF應用中,可能客戶端和服務器端的 角色是可以互換的,例如服務器端一般可能僅僅提供操作服務,它並不需要主動 地聯系客戶端做什麼操作。
但是,假如某些時候,我們需要服務端也能 夠具備這樣的特征,就是說他能夠在某些時候主動地聯系客戶端,觸發一個行為 。
這種場景,我們簡單地歸納為“雙工”場景。下面來看看 在WCF中如何實現這種雙工的服務。
1. 創建一個用於回調的Contract。 它與標准的Contract沒有任何區別
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
namespace Contracts
{
/// <summary>
/// 這是一個回調的合約,用於服務器端對 客戶端進行回復
/// </summary>
[ServiceContract]
public interface ICallbackContract
{
[OperationContract]
void ServerReply(string originalMessage);
}
}
2. 在我們用於業務操作的Contract中,加入一個聲明,就是指 定回調的Contract類型是第一步創建的這個
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
namespace Contracts
{
[ServiceContract(CallbackContract=typeof(ICallbackContract))]
public interface IChatContract
{
[OperationContract]
void SendMessage (string message);
}
}
3. 在服務端的設 計
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using Contracts;
namespace Services
{
[ServiceBehavior (ConcurrencyMode=ConcurrencyMode.Multiple)]
public class ChatService:IChatContract
{
#region IChatContract 成員
public void SendMessage(string message)
{
Console.WriteLine(string.Format("{0} 收到客戶端的消息: {1}", DateTime.Now.ToString(), message));
ICallbackContract callback = OperationContext.Current.GetCallbackChannel<ICallbackContract> ();
callback.ServerReply("服務器處理 了"+message);//大家注意到,這裡,服務端可以根據情況發回一個回復的消息
}
#endregion
}
}
4.客戶端的設計
編寫一個實現了回調合約 的Handler,實際上就是說,如果服務器回復了消息,那麼客戶端自己該怎麼做
class CallbackHandler : Contracts.ICallbackContract {
#region ICallbackContract 成員
public void ServerReply(string originalMessage)
{
Console.WriteLine("{0} 收到服務器回復:{1}", DateTime.Now, originalMessage);
}
#endregion
}
創建服務的本地代理的時候,需要定義一個比較特殊的構造函數
class ChatServiceClient : ClientBase<Contracts.IChatContract>, Contracts.IChatContract {
public ChatServiceClient(InstanceContext callback,Binding binding, EndpointAddress address) : base (callback,binding, address) { }
#region IChatContract 成員
public void SendMessage(string message)
{
Channel.SendMessage(message);
}
#endregion
}
客戶端代碼
static void Main(string[] args)
{
Binding binding = new WSDualHttpBinding();//這裡必須用 WSDualHttpBinding
EndpointAddress address = new EndpointAddress("http://localhost:9000/ChatService");
CallbackHandler callback = new CallbackHandler();
ChatServiceClient proxy = new ChatServiceClient(new InstanceContext(callback),binding, address);
Console.Write("請輸入:");
string input = Console.ReadLine();
while (input != "Exit")
{
proxy.SendMessage(input);
Console.WriteLine();
Console.Write("請輸 入:");
input = Console.ReadLine();
}
}
最後我們看到的就是一個簡單的聊天程序
初 始化狀態
聊天中的狀態