C#實(shí)現(xiàn)插件構(gòu)架淺析
C#語(yǔ)言有很多值得學(xué)習(xí)的地方,這里我們主要介紹C#實(shí)現(xiàn)插件構(gòu)架,包括介紹幾個(gè)解決方案的對(duì)比等方面。
假設(shè)你設(shè)計(jì)的程序已經(jīng)部署到用戶的計(jì)算機(jī)上,并且能夠正常運(yùn)行了。但是有一天,用戶打來(lái)了電話——他們要求增加新的功能。確定了用戶的需求后,你竟然發(fā)現(xiàn)原有的軟件架構(gòu)已經(jīng)無(wú)法勝任新增任務(wù)的需求——你需要重新設(shè)計(jì)這個(gè)應(yīng)用了!但問(wèn)題是,就算你又用了一個(gè)開(kāi)發(fā)周期完成了用戶需要的應(yīng)用,卻不能保證用戶的需求不會(huì)再次變更。也就是說(shuō),需求蔓延的可能性依然存在。因此,這種情況下C#實(shí)現(xiàn)插件構(gòu)架更能顯示出它的優(yōu)越性。
一. 幾個(gè)解決方案的對(duì)比
我總結(jié)了一下我所接觸到的C#實(shí)現(xiàn)插件構(gòu)架,大致上可分為以下幾類:
1.腳本式
使用某種語(yǔ)言把插件的程序邏輯寫(xiě)成腳本代碼。而這種語(yǔ)言可以是 Python ,或是其他現(xiàn)存的已經(jīng)經(jīng)過(guò)用戶長(zhǎng)時(shí)間考驗(yàn)的腳本語(yǔ)言。甚至,你可以自行設(shè)計(jì)一種腳本語(yǔ)言來(lái)配合你程序的特殊需要。當(dāng)然,用當(dāng)今***的 XML 是再合適不過(guò)了。
這種形式的特點(diǎn)在于,稍有點(diǎn)編程知識(shí)的用戶就可以自行修改你的腳本( ^_^ 假如你不加密它的話)。我們無(wú)法論證這是好處還是壞處。因?yàn)?,這種情況所造成的后果是不可預(yù)知的。
2.動(dòng)態(tài)函數(shù)庫(kù) DLL
插件功能以動(dòng)態(tài)庫(kù)函數(shù)的形式存在。主程序通過(guò)某種渠道(插件編寫(xiě)者或某些工具)獲得插件 DLL 中的函數(shù)簽名,然后在合適的地方調(diào)用它們。用過(guò) Matlab 的讀者都知道, Matlab 中的各項(xiàng)功能幾乎都是些動(dòng)態(tài)鏈入的函數(shù)。
3.聚合式
顧名思義,就是把插件功能直接寫(xiě)成 EXE 。主程序除了完成自己的職責(zé)外,還負(fù)責(zé)調(diào)度這些“插件”。我不喜歡這種形式。這使插件與插件之間,主程序與插件之間(主要是這一點(diǎn))的信息交流困難了許多。巴比倫塔的失敗 [1] 從某種程度上講就是信息交流無(wú)法實(shí)現(xiàn)造成的。
4.COM 組件
COM [2] 的產(chǎn)生給這個(gè)世界增添了幾分活力。只有接口!我們的插件需要做的只是實(shí)現(xiàn)程序定義的接口。主程序不需要知道插件怎樣實(shí)現(xiàn)預(yù)定的功能,它只需要通過(guò)接口訪問(wèn)插件,并提供主程序相關(guān)對(duì)象的接口。這樣一來(lái),主程序與各插件之間的信息交流就變得異常簡(jiǎn)單。并且,插件對(duì)于主程序來(lái)說(shuō)是完全透明的。
二. 決策
C# 是面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言。它提供了 interface 關(guān)鍵字來(lái)直接定義接口。同時(shí), System.Reflection 命名空間也提供了訪問(wèn)外部程序集的一系列相關(guān)對(duì)象。這就為我們?cè)贑#實(shí)現(xiàn)插件構(gòu)架打下了堅(jiān)實(shí)的基礎(chǔ)。
【編輯推薦】