Managed Extensibility Framework (MEF)

小弟季義欽發表於2013-08-27

最近C#專案遇到一個問題,我編寫了一個開機啟動的服務,有兩個目的:

(1)客戶端執行時需要用到一些快取,但是這些快取的載入(從伺服器端獲取)有些耗時,所以就想要開啟一個服務在客戶端開啟之前就開始獲取這些快取,等到客戶端啟動的時候將這些快取通過命名管道傳遞給他。 這些快取包括資料字典,使用者資訊,等等,以後可能還會有更多的快取;

(2)後臺執行的一個客戶端代理服務的介面(托盤形式)需要顯示這些快取當前的狀態,比如資料字典有多少,是否正常,重新整理時間是多少等等。我們的這個windows服務就在獲取了快取之後構造出快取狀態資訊通過命名管道傳遞給這個托盤讓它來顯示。


問題是我們目前雖然已經確定了有資料字典快取,但是以後可能還會增加新的快取,不可能每次增加一種快取,我們都修改編寫的這個服務,新增獲取新型別快取的程式碼,以後構造其狀態資訊結構的程式碼。

所以為了可擴充性,我決定這樣做:

(1)為所有快取獲取者編寫一個介面ICacheGetter,包含方法DataSet getCache() ; 以後增加新的快取的時候,就讓其他人編寫新的快取獲取類繼承自這個介面;

(2)針對快取狀態資訊構造,也定義這樣一個介面ICacheStatInfoBuilder,包含一個方法string buildCacheStatStr(DataSet cache); 將快取作為引數傳遞進去,讓其他人編寫根據快取內容構造快取狀態資訊描述字串的方法的實現;

所有的快取獲取者(ICacheGetter實現類)都需要將自己配置到一個配置檔案中,同樣所有的快取狀態資訊構造者(ICacheStatInfoBuilder實現類)也需要將自己配置到對應的配置檔案中。


然後我的服務只需要負責:

(1)通過XMLDocument類來讀取配置檔案,通過反射機制例項化所有的快取獲取者,並呼叫它的快取獲取方法,並將獲取的DataSet存放到Dictionary<string,DataSet>中,通過命名管道將這個儲存了所有快取的容器傳送給客戶端;

(2)通過XMLDocument類來讀取配置檔案,通過反射機制例項化所有的快取資訊構造者,並呼叫它的快取狀態資訊構造方法,並將構造好快取狀態資訊描述字串存放到Dictionary<string,string>中,通過命名管道將這個儲存了所有快取狀態資訊字串的容器傳送給托盤;

(PS:應該也可以用註冊/通知,或者說訂閱/釋出的模式來實現)

想好之後我就準備開始動手了,沒想到和頭兒溝通之後,發現可以用非常簡單的方式來解決我的這個問題,沒錯,就是MEF


使用EMF解決這個問題大概是要做以下步驟 :

1 所有的快取獲取者/快取狀態資訊構造者 都將自己Export出來;

2 在windows服務中申明一個型別為ICacheGetter/ICacheStatInfoBuilder的列表容器;

3 呼叫一段程式碼(從官網拷貝),這段程式碼的作用就是掃描所有的指定目錄下面的dll,找到申明瞭Export的類之後,將它的例項注入到對應的2中申明的容器中;

OK,這樣你就可以直接迭代容器,訪問其中的物件,呼叫其方法了,很簡單啊有木有!

這個應該就和Java總Spring的依賴注入一個原理,通過載入dll,利用反射技術建立類物件,注入到對應的容器中。


關於更多MEF的資訊請檢視:http://msdn.microsoft.com/zh-cn/library/vstudio/dd460648.aspx

(轉載請註明出處,jiq)

Managed Extensibility Framework 或 MEF 是一個用於建立可擴充套件的輕型應用程式的庫。應用程式開發人員可利用該庫發現並使用擴充套件,而無需進行配置。擴充套件開發人員還可以利用該庫輕鬆地封裝程式碼,避免生成脆弱的硬依賴項。通過 MEF,不僅可以在應用程式內重用擴充套件,還可以在應用程式之間重用擴充套件。


相關文章