zoukankan      html  css  js  c++  java
  • ESFramework介绍之(26)-- 支持复杂插件(InnerDealer 和 InnerDispatcher)

        (本文内容适合于 ESFramework V0.2+)
        通常,最单纯的情况是一个插件对应某一特定类型的功能请求,但是,在有的应用中也会出现这样的情况,有多种类型的功能请求相互关联、并且可能交叉,如果是这样,对应每种类型的请求都开发一个插件可能会非常困难,因为这可能会牵涉到插件之间的相互引用/访问,这违背了插件的“自治”性。最好的办法还是将它们放在一个插件中,通过ServiceItemIndex(你一定还记得消息头定义中除了ServiceKey外还有个ServiceItemIndex属性)来区分相互关联的各种请求类型。
        当涉及的请求类型非常多时,我们的插件会变得非常复杂,通常的解决方案是在插件内部构建“内部处理器”InnerDealer,然后将ServiceItemIndex映射到对应的“内部处理器”上,这个映射可以由“内部分派器”InnerDispatcher完成。需要注意的是,并不需要为每个ServiceItemIndex都构建一个“内部处理器”,一个“内部处理器”可能能处理多个ServiceItemIndex的请求类型。下面我们重点关注“内部处理器”和“内部分派器”的实现。
       
        内部分配器接口IInnerDispatcher定义如下:
        public interface IInnerDispatcher
        {        
            
    string AddinAssemblyName{set ;} //本插件程序集的名称

            
    void Initialize() ;
            IInnerDealer GetDealer(
    int serviceIndex) ;
        }

        最主要是GetDealer()方法的实现,它根据消息头中的ServiceItemIndex返回对应的内部处理器,你也许想到了,这可以通过Switch分支将serviceItemIndex映射到对应的内部处理器,然后这种集中管理的方式不是很方便,比如,当增加/删除一个内部处理器时,就要在这里增加/删除对应的分支语句。更好的办法是,让内部处理器能自己暴露它能处理的ServiceItemIndex的集合,这样,在运行时,可以通过反射动态的构建Mapping表,从而就避开了Switch语句及其引入的繁琐。
        内部处理器接口定义如下,它通过ServiceIndexCollection属性暴露了它能处理的ServiceItemIndex集合。
        public interface IInnerDealer
        {
            
    int[] ServiceIndexCollection{get ;}

            NetMessage DealRequest(NetMessage reqMsg) ;
        }
        
        现在,我们可以实现IInnerDispatcher的Initialize方法来动态构建Mapping表了:
            private void Initialize()
            {
                Assembly[] asses 
    = AppDomain.CurrentDomain.GetAssemblies();
                Type supType 
    = typeof(IInnerDealer)  ;

                
    foreach (Assembly ass in asses)
                {
                    
    string[] names = ass.FullName.Split(',') ;
                    
    if(names[0].Trim() == this.addinAssemblyName)
                    {
                        
    foreach(Type t in ass.GetTypes())
                        {
                            
    if(supType.IsAssignableFrom(t) && (!t.IsAbstract) && (! t.IsInterface) )
                            {
                                IInnerDealer dealer 
    = (IInnerDealer)Activator.CreateInstance(t) ;
                                
    if(dealer.ServiceIndexCollection != null)
                                {
                                    
    foreach(int serKey in dealer.ServiceIndexCollection)
                                    {
                                        
    this.htDealer.Add(serKey ,dealer) ;
                                    }
                                }
                            }
                        }

                        
    break ;
                    }
                }
            }

        可以在IAddin.OnLoading方法中调用InnerDispatcher的Initialize方法进行初始化。

        IInnerDispatcher的GetDealer方法就显而易见了:
            public IInnerDealer GetDealer(int serviceIndex)
            {
                
    return (IInnerDealer)this.htDealer[serviceIndex] ;
            }

        功能插件的DealRequestMessage就变得相当简单:
            public ESFramework.Network.NetMessage DealRequestMessage(ESFramework.Network.NetMessage reqMsg)
            {        
                IInnerDealer dealer 
    = this.dispatcher.GetDealer(reqMsg.Header.ServiceItemIndex) ;
                
    if(dealer == null)
                {
                    
    return null ;
                }

                
    return dealer.DealRequest(reqMsg) ;
            }
        
        插件中接下来需要做的工作就是实现你需要的IInnerDealer,实现的内部处理器不需要进行注册,它会在初始化插件时动态创建并被加入到Mapping表。需要注意的是,内部处理器的实现必须有一个无参的构造函数,否则,反射创建处理器实例将会抛出异常。
       

    上一篇文章:ESFramework介绍之(25)-- 在插件中使用NHibernate

    转到  :ESFramework 可复用的通信框架(序) 
  • 相关阅读:
    poj3122
    poj1323
    poj1328
    poj1700
    poj2586
    存储过程
    java基础3
    springmvc ---->helloworld
    选取下拉框,显示对应的图片
    java基础2
  • 原文地址:https://www.cnblogs.com/zhuweisky/p/384896.html
Copyright © 2011-2022 走看看