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);
}
}
}
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;
}
}
}
}
}
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;
}
}
}
}
}