应用框架的设计与实现——.NET平台(7.事件通知服务.源码分析)


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

            }

        }

    }

}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值