EventClient.cs using System; using System.Reflection; using System.Collections; using System.Threading; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels.Http; using System.Runtime.Remoting.Channels; using System.Runtime.Serialization; using System.Runtime.Remoting.Activation; namespace SAF.EventNotification ... { /**//// <summary> /// EventClient 部署在客户端 /// 因为需要与服务端通信,必须是可序列化的,所以继承自 MarshalByRefObject /// </summary> public class EventClient : MarshalByRefObject ...{ public delegate void EventProcessingHandler(string eventName,object content); public delegate void RepeaterHandler(string eventName, object content); private EventServer es; // 事件.{方法} private Hashtable repeatDelegate= new Hashtable(); public EventClient(string url) ...{ // 注册一个双向通信(端口号为0)的信道 IDictionary props = new Hashtable(); props["port"] = 0; BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider(); HttpChannel channel = new HttpChannel(props, clientProvider,null); ChannelServices.RegisterChannel(channel); // 获取远程代理类,远程类必须是Singleton类型的,才能保证获取的是同一个对象的代理 es = (EventServer)Activator.GetObject(typeof(EventServer),url); } /**//// <summary> /// 增加一个方法的注册 /// </summary> /// <param name="eventName">event name</param> /// <param name="s">delegate on the client side that process the event notification</param> public void SubscribeEvent(string eventName, EventProcessingHandler s) ...{ try ...{ // 检查该事件是否已注册过 Delegate handler =(Delegate)repeatDelegate[eventName]; // 如果事件注册过,将新注册的委托加入原有事件委托的列表中 Delegate.Combine(handler, s); // hashtable 的事件委托重新指向新委托链 if (handler != null) ...{ //chain up the delegates together handler = Delegate.Combine(handler, s); //reset the delegate object in the hashtable repeatDelegate[eventName] = handler; } else ...{ // 如果事件没有注册过,在hashtable中加入新的事件名及其委托 // 生成一个新的EventProcessingHandler委托 在服务端注册 // 为什么使用新生成的委托对象注册,而不用原有的委托来注册?? // 个人认为是其它对象没有与服务端通信的信道,只有EventClient注册过这样的信道。 // 顺带着的好处是服务端不用按照事件注册的方法数发通知,只需按照事件注册的客户数发通知即可。 repeatDelegate.Add(eventName,s); EventClient.EventProcessingHandler repeat = new EventClient.EventProcessingHandler(Repeat); //subscribe the "repeat" delegate to the EventServer. es.SubscribeEvent(eventName,repeat); } } catch (Exception ex) ...{ Console.WriteLine(ex.Message); } } /**//// <summary> /// 撤销一个方法的注册 /// </summary> /// <param name="eventName">event name</param> /// <param name="s">delegate on the client side that process the event notification</param> public void UnSubscribeEvent(string eventName, EventProcessingHandler s) ...{ // 取出相关事件的委托链 Delegate handler =(Delegate)repeatDelegate[eventName]; // 如果委托不为空,撤销该方法的注册 Delegate.Remove(handler, s); if (handler != null) ...{ handler = Delegate.Remove(handler, s); //reassign the chain back to the hashtable. repeatDelegate[eventName] = handler; } } /**//// <summary> /// EventClient接到服务端的消息通知后的处理方法 /// </summary> /// <param name="eventName">event name</param> /// <param name="content">the content of the notification</param> public void Repeat(string eventName, object content) ...{ // 从 hashtable 中取出事件的委托链 EventProcessingHandler eph = (EventProcessingHandler)repeatDelegate[eventName]; // 如果委托不为空,向这些委托发送消息通知 if (eph !=null) ...{ eph(eventName, content); } } /**//// <summary> /// 发布一个事件的消息 /// </summary> /// <param name="eventName">event name</param> /// <param name="content">event content</param> public void RaiseEvent(string eventName, object content) ...{ es.RaiseEvent(eventName,content); } }} EventServer.cs using System; using System.Collections; using SAF.EventNotification; namespace SAF.EventNotification ... { /**//// <summary> /// EventServer 部署在服务端 /// </summary> public class EventServer : MarshalByRefObject ...{ // 事件.{客户} private Hashtable delegateMap =new Hashtable(); public EventServer() ...{ } /**//// <summary> /// keep the EventServer live forever /// </summary> /// <returns></returns> public override object InitializeLifetimeService() ...{ //object live indefinitely return null; } /**//// <summary> /// 注册一个客户端事件 /// 类型是 EventClient.EventProcessingHandler /// </summary> /// <param name="eventName">event name</param> /// <param name="handler">client side delegate</param> public void SubscribeEvent(string eventName, EventClient.EventProcessingHandler handler) ...{ //ensure that only one thread modify the delegate chain at a time. lock(this) ...{ Delegate delegateChain = (Delegate)delegateMap[eventName]; // 检查事件是否注册过,如果没有注册过加入hashtable即可 if (delegateChain == null) ...{ delegateMap.Add(eventName,handler); } else ...{ // 如果事件注册过,将委托加入事件的委托链中 delegateChain = Delegate.Combine(delegateChain, handler); // 事件委托指向新委托链地址 delegateMap[eventName] = delegateChain; } } } /**//// <summary> /// 撤销注册 /// </summary> /// <param name="eventName">event name</param> /// <param name="handler"></param> public void UnSubscribeEvent(string eventName, EventClient.EventProcessingHandler handler) ...{ //ensure that only one thread modify the delegate chain at a time. lock(this) ...{ Delegate delegateChain = (Delegate)delegateMap[eventName]; // 事件委托存在的话,从委托链中删除委托 if (delegateChain != null) ...{ //remove the delegate from the chain delegateChain = Delegate.Remove(delegateChain,handler); // 将委托指针指向新的委托链 delegateMap[eventName] = delegateChain; } } } /**//// <summary> /// 发布消息 /// </summary> /// <param name="eventName">event name</param> /// <param name="content">content of the notification</param> public void RaiseEvent(string eventName, object content) ...{ Delegate delegateChain = (Delegate)delegateMap[eventName]; // 取得当前委托的链结构,不受后面的删除操作影响 IEnumerator invocationEnumerator = delegateChain.GetInvocationList().GetEnumerator(); //loop through each delegate and invoke it. while(invocationEnumerator.MoveNext()) ...{ Delegate handler = (Delegate)invocationEnumerator.Current; try ...{ handler.DynamicInvoke(new object[]...{eventName,content}); // 发布消息 } catch (Exception ex) ...{ // 产生异常时删除当前委托,并且将事件委托链指向新委托链 delegateChain = Delegate.Remove(delegateChain, handler); delegateMap[eventName] = delegateChain; } } } }}