【转载】企业级服务器设计与实现经验之插件系统基础篇
最初之所以要采用插件的形式進行開發,主要是為了解決功能服務的“熱插拔”問題,在決定采用“框架+插件”的方式進行設計后,我們就更進一步,打算將一個個可以分割開來的擁有完整功能的組件都做成插件的形式,并且使同類型的插件的接口兼容,這樣在以后需要改變時就可以靈活的進行替換。比如,將通信部分做成通信插件、日志記錄部分做成日志插件等等。
?
首先,我們要弄清楚,什么是插件?我給出了一個定義,可能有失偏頗。
?
??? 插件又稱為擴展,是一種特殊的組件,用于增強和擴展基本框架的行為能力。插件和框架的通信協議是一組接口,插件的各種特性都可以通過該接口進行訪問。插件主要有如下特點:
?
(1)一個插件是一個獨立的物理單元。它可以獨立的提供一項完整的服務(功能),而不需要依賴于其它插件。
?
(2)插件能自我描述 ―― 插件的所有對外的發布信息都由插件自己內部提供,而不依賴于外部文件或注冊表。
?
(3)插件能自我管理 ―― 插件如果需要配置信息,則插件自己能讀取和修改配置信息,而不是框架來完成這些事情。
(4)插件自我獨立?? ―― 一個插件不得引用其它的插件。如果一個插件與另一個插件關系緊密,那么應該將這兩個插件合成一個插件,或者重新分解為兩個獨立的插件.?
?
在DataServer系統中,所有的插件從IAddin繼承,IAddin接口定義如下:?
?
public?interface?IAddin
???? {
????????void?Start()?;?//不同類型的插件對開始和停止的解釋不一樣,如果一個插件沒有此意義,可實現為空
????????void?Stop()?;
????????int?ServiceKey {get?;}?
????????string?ServiceName {get?;}?????
????????string?Description {get?;}?//插件說明信息
????????AddinAppendixInfo?AddinAppendixInfo {get?;}?
????????string?AddinType {get?;}
????}????
?
接口中的所有方法屬性的意義一目了然,其中,ServiceKey是插件關鍵字,用于區分不同的插件。我們可以把同一類型的插件的關鍵字限定在某個范圍之內,比如,我將通信插件的關鍵字范圍限定在2000-2999之間。AddinAppendixInfo用于描述插件的附加信息,如作者、創建日期、版本號等。
?
public?class?AddinAppendixInfo
???? {
????????public?string?Author?;
????????public?string?TimeCreated?;
????????public?string?TimeLastRevised?;
????????public?string?AddinVersion?;
????}
?
?
?
AddinType是插件類型,在DataServer中,有如下幾種插件類型:
?
public?class?AddinTypes
???? {
????????public?const?string?Net????????????????=?"通信插件"?;
????????public?const?string?Function???????????=?"功能插件"?;
????????public?const?string?Reporter???????????=?"報告者插件"?;
????????public?const?string?BasicReqDealer?????=?"基本請求處理者插件"?;
????????public?const?string?RespondInterceptor?=?"回復截獲者插件"?;
????}
?
每種類型的插件的功用將在后面說明。
?
?
?
大部分插件都需要進行配置,我將配置部分抽象為一個公共的接口,IAddinConfig定義如下:
?
public?interface?IAddinConfig
???? {
????????//以下方法返回的控件或窗體必須實現EnterpriseServerBase.Configure.IConfigControl接口
????????IConfigControl?GetAddinConfigForm()?;
????????IConfigControl?GetAddinConfigControl()?;????????
????}
?
這樣,一個插件如果需要配置信息,則實現該接口即可。前面已經提到“插件如果需要配置信息,則插件自己能讀取和修改配置信息,而不是框架來完成這些事情”,插件就是通過IAddinConfig接口來操作配置信息的。GetAddinConfigForm用于獲取一個獨立的配置窗體,通過此窗體可以完成對插件配置,而GetAddinConfigControl獲取的是一個配置控件,一般其結構與功能和配置窗體一樣,只不過它可以嵌入到其它任意的窗體中,比如到時,我們可以在主框架中設置一個專門用于配置的TabControl,而其中的每一頁就用于加載一個GetAddinConfigControl返回的配置控件,從而實現對配置的統一管理。
?
IConfigControl究竟是如何操作配置信息的?其定義如下:
?
public?interface?IConfigControl
???? {
????????bool?Initialize(string?configPath?,string?objName)?;?//objName?是配置文件中的對象名
????????bool?SaveConfig()?;
????????bool?ReDisplayConfigInfo()?;?//顯示更新后的配置信息
????????event?EventHandler?ConfigChanged?;?
????}????
?
一般,配置信息保存于配置文件中,所以初始化時要給出配置路徑,而objName參數的作用,可以參見前面的《如何使用XCodeFactory自動生成XML配置文件和對應的解析類?》這篇文章,我的所有于配置文件相關的解析類和配置窗體都是通過XCodeFactory自動生成的。XCodeFactory接口的其它幾個方法的意思很明顯,就不用解釋了。
?
接下來,我們看看如何將插件加載到系統中。
?
我們都知道,一個插件是一個獨立的物理單元,我們如何獲得該插件的類型了?有很多辦法可以解決,比如,我們訪問插件目錄下的每個插件,通過Assembly.LoadFrom加載一個插件,然后Type. IsSubclassOf查看其是否實現了某種插件類型的接口,從而判斷其類型。我采用了更直觀的方式,用插件的名字來標志其類型,比如所有的通信插件都以NetAddin.dll結尾。
?
可以用一個特定的模塊來加載插件,我稱之為“插件加載器”,插件加載器用于加載某目錄下的所有特定類型的插件,"特定"表現在兩個方面:(1)插件的名字以[addinSign].dll結尾;(2)插件中的主類是從[baseAddinType]繼承。插件加載器的接口定義如下:
?
public?interface?IAddinLoader
???? {????????????
????????ArrayList?LoadAddins(string?addinFolderPath?,string?addinSign?,Type?baseAddinType)?;
????}
?
很簡單,只有一個方法,該方法加載某目錄下的所有某特定類型的插件,而返回的列表中的每個元素就引用著一個插件。
?
插件加載器僅僅負責將某種類型的插件加載進來,但是如何實現將所有的插件加載進來、并動態的加載/移除插件了?我們需要一個管理器組件來完成這件事情,它就是IAddinManagement,其接口定義如下:
?
public?interface?IAddinManagement
???? {
????????void?LoadAllAddins(string?addin_FolderPath?)?;
????????bool?ReLoadAddins(out?int?increment)?;
????????void?UnloadAllAddins()?;
????????bool?DynRemoveAddin(int?serviceKey)?;
????????bool?DynRemoveAddin(string?serviceName)?;
????????void?StartAllAddin()?;
????????void?StopAllAddin()?;
????????ArrayList?AddinBoxList? {get?;}????????
????????Hashtable?GetAllServiceList()?;?//key?-?name
????????event?CallBackSimple?AddinsChanged?;
????}
?
可以看到,IAddinManagement實現了對所有插件的全部管理,其還發布了一個事件AddinsChanged,就是當插件列表發生變化的時候用于通知外部。
?
關于插件的基礎部分,就先介紹這么多,在后面的章節中,我們將深入到各種類型的插件的內部。
轉載于:https://www.cnblogs.com/fx2008/archive/2011/11/24/2261184.html
總結
以上是生活随笔為你收集整理的【转载】企业级服务器设计与实现经验之插件系统基础篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何使用.NET配置文件(一)
- 下一篇: Linux/Ubuntu sudo不用输