WCF实现事件通知是一个比较容易掌握的知识点,不过在实现的过程中,我们还是需要注意一些事项,以保证功能的完善性。
WCF中有一些方法的应用对于初学者来说还是比较容易应用。只要熟练的联系这些方法操作,一般都能牢固的掌握。看了一些WCF的例子,实现事件通知使用的是多播委托的特性,有点复杂,操作起来也不是很直观,看到一堆委托和事件我一般头就晕了。
下面介绍一种使用观察者模式WCF实现事件通知的简单方法。没别的,就是简单,简单最美。
工程代码如下:
WCF实现事件通知1.定义接口
1 [ServiceContract(SessionModeSessionMode = 2 SessionMode.Required, CallbackContract 3 = typeof(IWriteLogCallback))] 4 public interface ILogService 5 { 6 [OperationContract(IsInitiating = 7 true, IsTerminating = false)] 8 void Write(string logMsg); 9 [OperationContract(IsInitiating = 10 true, IsTerminating = false)] 11 void RegisterListener(); 12 [OperationContract(IsInitiating = 13 false, IsTerminating = false)] 14 void UnregisterListener(); 15 } 16 [ServiceContract] 17 public interface IWriteLogCallback 18 { 19 [OperationContract(IsOneWay = true)] 20 void OnWriteLog(string logMsg); 21 }
为了简单举了一个写日志的例子, Write(string logMsg)就是写入日志的方法,参数logMsg是需要写入的日志信息。当客户单没有调用RegisterListener()订阅事件的时候,是不会收到写日志的事件通知的,相应的要获得写日志的事件通知,就需要调用RegisterListener()方法。如果要取消订阅就调用UnregisterListener()方法。写日志的功能和事件的订阅功能是分开的。
WCF实现事件通知2.服务实现
1 [ServiceBehavior( 2 IncludeExceptionDetailInFaults = true, 3 InstanceContextModeInstanceContextMode = 4 InstanceContextMode.Single, 5 ConcurrencyModeConcurrencyMode = 6 ConcurrencyMode.Multiple)] 7 class LogService:ILogService 8 { 9 public LogService() 10 { 11 Trace.WriteLine("Create LogService Instance."); 12 } 13 Dictionary<string, OperationContext> 14 listeners = new Dictionary<string, 15 OperationContext>(); 16 private void BroadCast(string logMsg) 17 { 18 List<string> errorClints = new List<string>(); 19 foreach (KeyValuePair<string, OperationContext> 20 listener in listeners) 21 { 22 try 23 { 24 listener.Value.GetCallbackChannel 25 <IWriteLogCallback>().OnWriteLog(logMsg); 26 } 27 catch (System.Exception e) 28 { 29 errorClints.Add(listener.Key); 30 Trace.WriteLine("BROAD EVENT ERROR:" + e.Message); 31 } 32 } 33 foreach (string id in errorClints) 34 { 35 listeners.Remove(id); 36 } 37 } 38 #region ILogService 成员 39 public void Write(string logMsg) 40 { 41 Trace.WriteLine("Write LOG:"+logMsg); 42 BroadCast(logMsg); 43 } 44 public void RegisterListener() 45 { 46 listeners.Add(OperationContext.Current. 47 SessionId, OperationContext.Current); 48 Trace.WriteLine("SessionID:" + 49 OperationContext.Current.SessionId); 50 Trace.WriteLine("Register listener. 51 Client Count:" + listeners.Count.ToString()); 52 } 53 public void UnregisterListener() 54 { 55 listeners.Remove(OperationContext 56 .Current.SessionId); 57 Trace.WriteLine("SessionID:" + 58 OperationContext.Current.SessionId); 59 Trace.WriteLine("Unregister listener. 60 Client Count:" + listeners.Count.ToString()); 61 } 62 #endregion 63 } Dictionary<string, OperationContext>
listeners包含了所有的事件订阅者。发布事件的时候,如果调用订阅者的回调函数失败,就把该订阅者从listeners移除。代码很简单,就不多说了。
WCF实现事件通知3.客户端访问
定义回调的客户端:
1 class LogClient:IWrite 2 LogCallback 3 { 4 #region IWriteLog 5 Callback 成员 6 public void OnWriteLog 7 (string logMsg) 8 { 9 Trace.WriteLine("RECV 10 LOG EVENT:" + logMsg); 11 } 12 #endregion 13 }
然后在程序中使用它:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Trace.Listeners.Add(new 6 ConsoleTraceListener()); 7 LogClient client = new LogClient(); 8 ILogService service = 9 DuplexChannelFactory<ILogService>. 10 CreateChannel(client, 11 new WSDualHttpBinding(), new 12 EndpointAddress("http: 13 //localhost:8888/log")); 14 //订阅消息 15 service.RegisterListener(); 16 service.Write("Client start"); 17 Console.WriteLine("Press 18 enter key to exit."); 19 Console.ReadLine(); 20 service.UnregisterListener(); 21 }
WCF实现事件通知需要注意的问题:
A. 因为客户也要监听端口,所以确保防火墙没有对它进行阻止。
B. 这里使用的是单实例的服务,所以需要进行多进程访问的保护,才能实际使用。
本文来自:http://developer.51cto.com/