WCF實(shí)現(xiàn)事件通知相關(guān)應(yīng)用技巧介紹
WCF中有一些方法的應(yīng)用對(duì)于初學(xué)者來(lái)說(shuō)還是比較容易應(yīng)用。只要熟練的聯(lián)系這些方法操作,一般都能牢固的掌握??戳艘恍¦CF的例子,實(shí)現(xiàn)事件通知使用的是多播委托的特性,有點(diǎn)復(fù)雜,操作起來(lái)也不是很直觀,看到一堆委托和事件我一般頭就暈了。#t#
下面介紹一種使用觀察者模式WCF實(shí)現(xiàn)事件通知的簡(jiǎn)單方法。沒(méi)別的,就是簡(jiǎn)單,簡(jiǎn)單最美。
工程代碼如下:
WCF實(shí)現(xiàn)事件通知1.定義接口
- [ServiceContract(SessionModeSessionMode =
 
SessionMode.Required, CallbackContract
= typeof(IWriteLogCallback))]- public interface ILogService
 - {
 - [OperationContract(IsInitiating =
 
true, IsTerminating = false)]- void Write(string logMsg);
 - [OperationContract(IsInitiating =
 
true, IsTerminating = false)]- void RegisterListener();
 - [OperationContract(IsInitiating =
 
false, IsTerminating = false)]- void UnregisterListener();
 - }
 - [ServiceContract]
 - public interface IWriteLogCallback
 - {
 - [OperationContract(IsOneWay = true)]
 - void OnWriteLog(string logMsg);
 - }
 
為了簡(jiǎn)單舉了一個(gè)寫(xiě)日志的例子, Write(string logMsg)就是寫(xiě)入日志的方法,參數(shù)logMsg是需要寫(xiě)入的日志信息。當(dāng)客戶單沒(méi)有調(diào)用RegisterListener()訂閱事件的時(shí)候,是不會(huì)收到寫(xiě)日志的事件通知的,相應(yīng)的要獲得寫(xiě)日志的事件通知,就需要調(diào)用RegisterListener()方法。如果要取消訂閱就調(diào)用UnregisterListener()方法。寫(xiě)日志的功能和事件的訂閱功能是分開(kāi)的。
WCF實(shí)現(xiàn)事件通知2.服務(wù)實(shí)現(xiàn)
- [ServiceBehavior(
 - IncludeExceptionDetailInFaults = true,
 - InstanceContextModeInstanceContextMode =
 
InstanceContextMode.Single,- ConcurrencyModeConcurrencyMode =
 
ConcurrencyMode.Multiple)]- class LogService:ILogService
 - {
 - public LogService()
 - {
 - Trace.WriteLine("Create LogService Instance.");
 - }
 - Dictionary<string, OperationContext>
 
listeners = new Dictionary<string,
OperationContext>();- private void BroadCast(string logMsg)
 - {
 - List<string> errorClints = new List<string>();
 - foreach (KeyValuePair<string, OperationContext>
 
listener in listeners)- {
 - try
 - {
 - listener.Value.GetCallbackChannel
 
<IWriteLogCallback>().OnWriteLog(logMsg);- }
 - catch (System.Exception e)
 - {
 - errorClints.Add(listener.Key);
 - Trace.WriteLine("BROAD EVENT ERROR:" + e.Message);
 - }
 - }
 - foreach (string id in errorClints)
 - {
 - listeners.Remove(id);
 - }
 - }
 - #region ILogService 成員
 - public void Write(string logMsg)
 - {
 - Trace.WriteLine("Write LOG:"+logMsg);
 - BroadCast(logMsg);
 - }
 - public void RegisterListener()
 - {
 - listeners.Add(OperationContext.Current.
 
SessionId, OperationContext.Current);- Trace.WriteLine("SessionID:" +
 
OperationContext.Current.SessionId);- Trace.WriteLine("Register listener.
 
Client Count:" + listeners.Count.ToString());- }
 - public void UnregisterListener()
 - {
 - listeners.Remove(OperationContext
 
.Current.SessionId);- Trace.WriteLine("SessionID:" +
 
OperationContext.Current.SessionId);- Trace.WriteLine("Unregister listener.
 
Client Count:" + listeners.Count.ToString());- }
 - #endregion
 - } Dictionary<string, OperationContext>
 
listeners包含了所有的事件訂閱者。發(fā)布事件的時(shí)候,如果調(diào)用訂閱者的回調(diào)函數(shù)失敗,就把該訂閱者從listeners移除。代碼很簡(jiǎn)單,就不多說(shuō)了。
WCF實(shí)現(xiàn)事件通知3.客戶端訪問(wèn)
定義回調(diào)的客戶端:
- class LogClient:IWrite
 
LogCallback- {
 - #region IWriteLog
 
Callback 成員- public void OnWriteLog
 
(string logMsg)- {
 - Trace.WriteLine("RECV
 
LOG EVENT:" + logMsg);- }
 - #endregion
 - }
 
然后在程序中使用它:
- class Program
 - {
 - static void Main(string[] args)
 - {
 - Trace.Listeners.Add(new
 
ConsoleTraceListener());- LogClient client = new LogClient();
 - ILogService service =
 
DuplexChannelFactory<ILogService>.
CreateChannel(client,- new WSDualHttpBinding(), new
 
EndpointAddress("http:
//localhost:8888/log"));- //訂閱消息
 - service.RegisterListener();
 - service.Write("Client start");
 - Console.WriteLine("Press
 
enter key to exit.");- Console.ReadLine();
 - service.UnregisterListener();
 - }
 
WCF實(shí)現(xiàn)事件通知需要注意的問(wèn)題:
A. 因?yàn)榭蛻粢惨O(jiān)聽(tīng)端口,所以確保防火墻沒(méi)有對(duì)它進(jìn)行阻止。
B. 這里使用的是單實(shí)例的服務(wù),所以需要進(jìn)行多進(jìn)程訪問(wèn)的保護(hù),才能實(shí)際使用。















 
 
 
 
 
 
 