(本文适用于 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!