ESFramework介绍之(29)―― 插件公共设施 AddinUtil

    (本文适用于 ESFramework V0.2+)
    不知你是否还记得,前面我们讲过,ESFramework规定了插件有如下特点:
(1)一个插件是一个独立的物理单元。它可以独立的提供一项完整的服务(功能),而不需要依赖于其它插件。
(2)插件能自我描述 ―― 插件的所有对外的发布信息都由插件自己内部提供,而不依赖于外部文件或注册表。
(3)插件能自我管理 ―― 插件如果需要配置信息,则插件自己能读取和修改配置信息,而不是框架来完成这些事情。
(4)插件自我独立   ―― 一个插件不得引用其它的插件。如果一个插件与另一个插件关系紧密,那么应该将这两个插件合成一个插件,或者重新分解为两个独立的插件。

    其实上述特点都为了一个目标,那就是插件的自治及与宿主应用的松耦合。我们希望,插件与宿主应用之间不要有信息共享,或者使这种共享尽可能的少。ESFramework中对插件的支持也很好的遵循了上述特点。但是,有时候应用程序迫不得已需要将某些引用(数据)传递到有需要的插件中,因为插件自己无法直接获取这些引用,而且这些引用可能会被多个组件/插件使用到。插件公共设施AddinUtil(位于ESFramework.Addins命名空间 )提供了一个场所或这说一个容器,宿主应用程序把需要共享给插件的数据放在这个容器中,而需要使用这些数据的插件从AddinUtil获取需要的数据。无疑,AddinUtil最好实现为一个静态类。

    public static class AddinUtil
    {
        private static Hashtable htUtil = Hashtable.Synchronized(new Hashtable()) ;

        public static void RegisterObject(string name ,object obj)
        {
            AddinUtil.htUtil.Add(name ,obj) ;
        }

        public static object GetObject(string name)
        {
            return AddinUtil.htUtil[name] ;
        }

        public static void Remove(string name)
        {
            AddinUtil.htUtil.Remove(name) ;
        }

        public static void Clear()
        {
            AddinUtil.htUtil.Clear() ;
        }
    }

    AddinUtil的实现非常简单,就不多讲了。下面举个例子。比如,功能服务器加载的多个功能插件需要解析各自收到的请求消息,消息解析需要IContractHelper组件的协助,IContractHelper的实现通常位于宿主应用(这里是FS)中,在每个插件中都实例化一个IContractHelper组件不仅性能上不划算,而且还可能会导致多个IContractHelper组件实例状态不一致的问题。甚至,更通常的情况,在插件实现中根本不应该看到IContractHelper的实现类,因为IContractHelper的实现类通常位于FS中(或FS引用的dll中),在插件中只能看到IContractHelper接口。
    FS在启动的时候,可以将IContractHelper引用注册到AddinUtil:

AddinUtil.RegisterObject("ContractHelper" ,MainClass.SpringContext.GetObject("contractHelper")) ;

    插件在加载回调IAddin.OnLoading方法中即可从AddinUtil中获取IContractHelper引用:

IContractHelper contractHelper = (IContractHelper)AddinUtil.GetObject("ContractHelper") ;

     AddinUtil就像一个中介者,宿主应用不会与任何一个插件紧密耦合,如果宿主应用需要与插件交换数据,通过AddinUtil是一种可行的方式。但是请记住,最好的方案是,宿主应用与插件之间不共享任何数据!只有在不得已的情况下才考虑使用AddinUtil!

上一篇: ESFramework介绍之(28)―― Udp组件

转到  :ESFramework 可复用的通信框架(序) 

时间: 2024-07-30 16:35:38

ESFramework介绍之(29)―― 插件公共设施 AddinUtil的相关文章

ESFramework介绍之(30)―― 消息侦察者 INetMessageSpy

    (本文适用于ESFramework V0.2+)     现在我们回想一下,当网络组件(Tcp/Udp组件)接收到一个消息后,这个消息会流经哪些组件,然后再通过网络组件发送出去了.如果你研究过ESFramework V0.1,你会发现,消息"行走"的路线模型可以用下图表示出来:    请求消息(路径由黑线表示)经过网络组件后,会被Hook链中的各个Hook按照特定的顺序处理,然后到达消息处理器,消息处理器处理请求消息,并给出回复消息(路径由红线表示),回复消息同样再经过Hook

ESFramework介绍之(8)-- 客户端插件IPassiveAddin

    前文已经提到了,在IServerAgent的基础上,客户端也可以采用插件的结构形式,客户端插件需要实现IPassiveAddin接口.    我的想法是,当客户端主程序加载一个新的PassiveAddin时,可以在某个菜单的子Items上添加一项,当双击这个子菜单项时,则弹出该客户端插件提供的"业务操作窗体".这只是使用客户端插件的可行方式之一,你完全可以根据你的应用来决定使用形式.IPassiveAddin接口定义如下:  1     /// <summary> 

ESFramework介绍之(13)-- 功能插件处理器工厂

    上文讲述的是AS中的基于连接池的消息处理器,现在我们把焦点转移到功能服务器FS上来,看看FS上消息分派的过程.当FS接收到到一个请求后,会从已加载的功能插件列表中选择一个合适的插件来处理这个消息,而每一个功能插件就相当于一个消息处理器.FS和AS的结构一致:    要注意的是,功能服务器FS上收到的所有消息都应该交给功能插件来处理,不存在其它的处理方式.这是使得FS"纯粹"的必须要求.上图已经很清楚的表示了功能插件处理器工厂的位置和作用.它借助插件管理器实现"工厂&q

ESFramework介绍之(9)-- 插件对(Addin Pair)调试“框架”

    使用ESFramework开发C/S(通常为4层.3层也没问题)应用,当需要增加一项新的业务时,我们需要做的仅仅是开发两个插件,一个是服务端的业务功能插件(FunAddin),一个是客户端插件(PassiveAddin),这两个插件合在一起称为Addin Pair.开发这两个插件,只需要关注于业务,而其它与业务无关的比如网络通信.加密.数据安全,都不用管.ESFramework很好的将这些关注点分离开来,使得写"业务"插件的程序员的工作变得非常单纯,在ESFramework介绍

ESFramework介绍之(20)―― 插件自动升级

    当我们的服务平台搭建成功后,所需要做的主要事情就是开发服务端功能插件(IFunAddin)和客户端插件(IPassiveAddin),每个插件对(AddinPair)实现了一组相似或相近的需求/功能.     好了,我们已经开发了十多对插件对,然后分别XCopy到了各个服务器节点上,"整个系统"已经投入了运行.通过前面的介绍(回顾),相信大家对我们的"整个系统"有了个大致的映像.我们的IRAS服务器通常只存在于一个节点上,而我们的AS和对应的多个FS通常分布

ESFramework介绍之(26)-- 支持复杂插件(InnerDealer 和 InnerDispatcher)

    (本文内容适合于 ESFramework V0.2+)    通常,最单纯的情况是一个插件对应某一特定类型的功能请求,但是,在有的应用中也会出现这样的情况,有多种类型的功能请求相互关联.并且可能交叉,如果是这样,对应每种类型的请求都开发一个插件可能会非常困难,因为这可能会牵涉到插件之间的相互引用/访问,这违背了插件的"自治"性.最好的办法还是将它们放在一个插件中,通过ServiceItemIndex(你一定还记得消息头定义中除了ServiceKey外还有个ServiceItem

ESFramework介绍之(18)―― Tcp用户管理器组件

    当我们的应用中客户端与AS之间是通过Tcp进行通信的时候,通常,应用也要求管理所有在线的用户.这种管理至少包含以下几点:(1) 当用户上线时,记录上线时间(2) 当用户请求服务时,记录请求服务的时间.服务的类型.本次服务下载的数据量(3) 当用户下线时,记录下线时间.并把本次用户登录.请求服务过程中的所有信息持久化保存(如记录到数据库)     在ESFramework中,实现这种管理的是ITcpUserManager组件,通常,该组件由AS使用(因为在AS.FS.IRAS中只有AS是必

ESFramework介绍之(17)―― 支持漫游用户和跨区域功能请求

    对于漫游用户的支持和跨区域功能请求的支持是ESFramework最基本的目的之一(回顾),在详细讲述解决方案之前,先了解一下关于这个问题的上下文.    在我们前面讲述的4层C/S架构中,每个AS负责一块区域.比如上海AS负责处理所有目标城市为上海的功能请求和管理所有在上海AS上注册的用户(比如PDA用户或手机用户).如果一个本是在上海注册的用户出差来到了武汉,最方便的,他会连上武汉的AS,这样对于武汉AS来说,这个用户就是漫游用户了.    如果上海的用户登陆上了上海的AS,但是他需要

ESFramework介绍之(14)-- AS与FS通信方案

    前面我们已经多次提到,每个AS都有一组FS为之服务(回顾),AS将接收到的功能请求通过Tcp连接池 或Remoting转发给某个FS处理.下面我们将深入讨论AS和FS之间的通信机制.     首先要解决第一个问题,AS如何知道每个为之服务的FS的地址?    最常见的一种解决方案是,AS处的配置文件中有一个FS地址列表,AS每次启动时,就读取这个列表,然后与列表中的每个FS建立Tcp连接池.这种方案很容易实现,但是有很多缺点.最主要的是当动态的添加/移除FS时,都需要修改AS配置文件中的