WCF开发工具是由微软公司推出的一款功能强大的开发插件,它在实际应用中可以为我们提供许多有用的帮助。在这里我们将会为大家详细介绍一下WCF事件通知的相关实现方法,以方便大家掌握这方面的应用技巧。#t#
看了一些WCF的例子,实现WCF事件通知使用的是多播委托的特性,有点复杂,操作起来也不是很直观,看到一堆委托和事件我一般头就晕了。下面介绍一种使用观察者模式实现事件通知的简单方法。没别的,就是简单,简单最美。
工程代码如下:
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);
- }
为了简单举了一个写日志的例子, Write(string logMsg)就是写入日志的方法,参数logMsg是需要写入的日志信息。当客户单没有调用RegisterListener()订阅事件的时候,是不会收到写日志的WCF事件通知的,相应的要获得写日志的事件通知,就需要调用RegisterListener()方法。如果要取消订阅就调用UnregisterListener()方法。写日志的功能和事件的订阅功能是分开的。
2.服务实现
- [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
包含了所有的事件订阅者。发布WCF事件通知的时候,如果调用订阅者的回调函数失败,就把该订阅者从listeners移除。代码很简单,就不多说了。
3.客户端访问
定义回调的客户端:
- class LogClient:IWriteLogCallback
- {
- #region IWriteLogCallback 成员
- 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事件通知实现时需要注意的问题:
A. 因为客户也要监听端口,所以确保防火墙没有对它进行阻止。
B. 这里使用的是单实例的服务,所以需要进行多进程访问的保护,才能实际使用。