Visual C# 插件構(gòu)架實(shí)戰(zhàn)_第1頁
Visual C# 插件構(gòu)架實(shí)戰(zhàn)_第2頁
Visual C# 插件構(gòu)架實(shí)戰(zhàn)_第3頁
Visual C# 插件構(gòu)架實(shí)戰(zhàn)_第4頁
Visual C# 插件構(gòu)架實(shí)戰(zhàn)_第5頁
已閱讀5頁,還剩1頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

VisualC#插件構(gòu)架實(shí)戰(zhàn)一、引言問題的引入假設(shè)你設(shè)計(jì)的程序已經(jīng)部署到用戶的計(jì)算機(jī)上,并且能夠正常運(yùn)行了。但是有一天,用戶打來了電話——他們要求增加新的功能。確定了用戶的需求后,你竟然發(fā)現(xiàn)原有的軟件架構(gòu)已經(jīng)無法勝任新增任務(wù)的需求——你需要重新設(shè)計(jì)這個(gè)應(yīng)用了!但問題是,就算你又用了一個(gè)開發(fā)周期完成了用戶需要的應(yīng)用,卻不能保證用戶的需求不會(huì)再次變更。也就是說,需求蔓延的可能性依然存在。因此,這種情況下插件構(gòu)架更能顯示出它的優(yōu)越性。幾個(gè)解決方案的對(duì)比我總結(jié)了一下我所接觸到的插件構(gòu)架,大致上可分為以下幾類:i>腳本式使用某種語言把插件的程序邏輯寫成腳本代碼。而這種語言可以是Python,或是其他現(xiàn)存的已經(jīng)經(jīng)過用戶長(zhǎng)時(shí)間考驗(yàn)的腳本語言。甚至,你可以自行設(shè)計(jì)一種腳本語言來配合你程序的特殊需要。當(dāng)然,用當(dāng)今最流行的XML是再合適不過了。這種形式的特點(diǎn)在于,稍有點(diǎn)編程知識(shí)的用戶就可以自行修改你的腳本(a_a假如你不加密它的話)。我們無法論證這是好處還是壞處。因?yàn)?,這種情況所造成的后果是不可預(yù)知的。ii>動(dòng)態(tài)函數(shù)庫(kù)DLL插件功能以動(dòng)態(tài)庫(kù)函數(shù)的形式存在。主程序通過某種渠道(插件編寫者或某些工具)獲得插件DLL中的函數(shù)簽名,然后在合適的地方調(diào)用它們。用過Matlab的讀者都知道,Matlab中的各項(xiàng)功能幾乎都是些動(dòng)態(tài)鏈入的函數(shù)。iii>聚合式顧名思義,就是把插件功能直接寫成EXE。主程序除了完成自己的職責(zé)外,還負(fù)責(zé)調(diào)度這些“插件”。我不喜歡這種形式。這使插件與插件之間,主程序與插件之間(主要是這一點(diǎn))的信息交流困難了許多。巴比倫塔的失?。?]從某種程度上講就是信息交流無法實(shí)現(xiàn)造成的。iv>COM組件COM[2]的產(chǎn)生給這個(gè)世界增添了幾分活力。只有接口!我們的插件需要做的只是實(shí)現(xiàn)程序定義的接口。主程序不需要知道插件怎樣實(shí)現(xiàn)預(yù)定的功能,它只需要通過接口訪問插件,并提供主程序相關(guān)對(duì)象的接口。這樣一來,主程序與各插件之間的信息交流就變得異常簡(jiǎn)單。并且,插件對(duì)于主程序來說是完全透明的。3.決策C#是面向?qū)ο蟮某绦蛟O(shè)計(jì)語言。它提供了interface關(guān)鍵字來直接定義接口。同時(shí),System.Reflection命名空間也提供了訪問外部程序集的一系列相關(guān)對(duì)象。這就為我們?cè)贑#中實(shí)現(xiàn)插件構(gòu)架打下了堅(jiān)實(shí)的基礎(chǔ)。下面,我們將以一個(gè)具有插件構(gòu)架的程序編輯器為例,來闡述這種構(gòu)架在C#中的實(shí)現(xiàn)。二、設(shè)計(jì)過程好了,現(xiàn)在我們準(zhǔn)備把所有的核心代碼都放在CSPluginKernel命名空間中。用VSIDE建立一個(gè)C#類庫(kù)工程。在命名空間CSPluginKernel中開始我們的代碼。1.接口設(shè)計(jì)我們的程序編輯器會(huì)向插件開放正在編輯的文檔對(duì)象。程序啟動(dòng)后,就枚舉每一個(gè)插件并把它連接到主程序,同時(shí)傳遞主程序?qū)ο蟮慕涌?。插件可以通過這個(gè)接口來請(qǐng)求主程序?qū)ο蠡蛟L問主程序功能。根據(jù)上面的需求,我們首先需要一個(gè)主程序接口:publicinterfaceIApplicationObject(voidAlert(stringmsg);//產(chǎn)生一條信息voidShowInStatusBar(stringmsg);//將指定的信息顯示在狀態(tài)欄IDocumentObjectQueryCurrentDocument();//獲取當(dāng)前使用的文檔對(duì)象IDocumentObject[]QueryDocuments();//獲取所有的文檔對(duì)象//設(shè)置事件處理器voidSetDelegate(DelegateswhichOne,EventHandlertarger);}//目前只需要這一個(gè)事件publicenumDelegates(Delegate_ActiveDocumentChanged,}然后是IDocumentObject接口。插件通過這個(gè)接口訪問編輯器對(duì)象。//////編輯器對(duì)象必須實(shí)現(xiàn)這個(gè)接口///publicinterfaceIDocumentObject(//這些屬性是RichTextBox控件的相應(yīng)的屬性映射stringSelectionText(get;set;}ColorSelectionColor(get;set;}FontSelectionFont(get;set;}intSelectionStart(get;set;}intSelectionLength(get;set;}stringSelectionRTF(get;set;}boolHasChanges(get;}voidSelect(intstart,intlength);voidAppendText(stringstr);voidSaveFile(stringfileName);voidSaveFile();voidOpenFile(stringfileName);voidCloseFile();_} 這個(gè)接口不需要過多解釋。這里我只實(shí)現(xiàn)了RichTextBox控件少數(shù)的幾個(gè)方法,其他可能用得到的,讀者自行添加即可。再然后,根據(jù)插件在其生命周期里的行為,設(shè)計(jì)插件的接口。//////本程序的插件必須實(shí)現(xiàn)這個(gè)接口///publicinterfaceIPlugin(ConnectionResultConnect(IApplicationObjectapp);voidOnDestory();voidOnLoad();voidRun();}//////表示插件與主程序連接的結(jié)果///publicenumConnectionResult(Connection_Success,Connection_Failed}主程序會(huì)首先調(diào)用Connect。方法,并傳遞IApplicationObject給插件。插件在這個(gè)過程中做一些初始化工作。然后,插件的OnLoad()方法被調(diào)用。在這之后,當(dāng)主程序接收到調(diào)用插件的信號(hào)時(shí)(鍵盤鼠標(biāo)響應(yīng))就會(huì)調(diào)用插件的Run()方法來啟動(dòng)這個(gè)插件。程序結(jié)束時(shí),調(diào)用其OnDestory()方法。這樣,插件的生命才宣告結(jié)束。2.插件信息的存儲(chǔ)與獲取一個(gè)插件需要有它的名稱、版本等信息。作為設(shè)計(jì)者的你,也一定要留下你的尊姓大名和個(gè)人網(wǎng)站等用來宣傳自己。C#的新特性一一屬性,就是一個(gè)很好的解決方案。因此我們定義一個(gè)從System.Attribute繼承來的類PluginInfoArrtibute://////用來指定一個(gè)插件的相關(guān)信息IIIpublicclassPluginInfoAttribute:System.Attribute(//////Deprecated.Donotuse.///publicPluginInfoAttribute。{}publicPluginInfoAttribute(stringname,stringversion,stringauthor,stringwebpage,boolloadWhenStart){//細(xì)節(jié)已略去}publicstringName{get{return_Name;}}publicstringVersion{get{return_Version;}}publicstringAuthor{get{return_Author;}}publicstringWebpage{get{return_Webpage;}}publicboolLoadWhenStart{get{return_LoadWhenStart;}}//////用來存儲(chǔ)一些有用的信息///publicobjectTag{get{return_Tag;}set{_Tag=value;}}//////用來存儲(chǔ)序號(hào)///publicintIndex{get{return_Index;}set{_Index=value;}}privatestring_Name="";privatestring_Version="";privatestring_Author="";privatestring_Webpage="";privateobject_Tag=null;privateint_Index=0;//暫時(shí)不會(huì)用privatebool_LoadWhenStart=true;}用這個(gè)類修飾你的插件,并讓他實(shí)現(xiàn)IPlugin接口://////MyPluging1(Justfortest)///[PluginInfo("MyPluging1(Justfortest)","1.0","JackHHansen","/matrix2003b",true)]publicclassMyPlugin1:IPlugin(publicMyPlugin1()(}#regionIPlugin成員//細(xì)節(jié)已略去#endregionprivateIApplicationObject_App;privateIDocumentObject_CurDoc;}加載插件現(xiàn)在就得用到System.Refelction命名空間了。程序在啟動(dòng)時(shí)會(huì)搜索plugins目錄下的每一個(gè)文件。對(duì)于每一個(gè)文件,如果它是一個(gè)插件,就用Assembly對(duì)象加載它。然后枚舉程序集中的每一個(gè)對(duì)象。判斷一個(gè)程序集是否為我們的插件的方法是判斷它是否直接或間接實(shí)現(xiàn)自IPlugin。用下面的函數(shù),傳遞從程序集枚舉的對(duì)象的System.Type。privateboolIsValidPlugin(Typet)(boolret=false;Type[]interfaces=t.GetInterfaces();foreach(TypetheInterfaceininterfaces)(if(the

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論