插件,意味著可擴展,且宿主程序不依賴于插件,即插即用。這種軟件設計方式可以使我們的應用程序大化地獲得可擴展性、適應性和穩(wěn)定性,而且便于軟件的維護和升級。在什么場景下使用插件呢?例如在本篇文章中,我個人有一個小需求就是希望記事本帶行號,于是我自己寫了一個極簡易的編輯器(CodeEditor),以這個編輯器為例,主體程序功能包括常見的新建、復制、查找、保存等已經(jīng)完成,但是在使用的過程中發(fā)現(xiàn)需要用到格式化這個功能,但是我還不想再去改主程序,這種情形下就可以通過插件來實現(xiàn),這樣以后在使用的時候,只要有新的需求就可以通過新增插件來實現(xiàn),從某種程度上講這也符合了開放-封閉的設計原則。下面對插件的定義來自百度百科。
成都創(chuàng)新互聯(lián)公司專注于企業(yè)全網(wǎng)營銷推廣、網(wǎng)站重做改版、沙河網(wǎng)站定制設計、自適應品牌網(wǎng)站建設、H5網(wǎng)站設計、商城建設、集團公司官網(wǎng)建設、成都外貿(mào)網(wǎng)站建設公司、高端網(wǎng)站制作、響應式網(wǎng)頁設計等建站業(yè)務,價格優(yōu)惠性價比高,為沙河等各大城市提供網(wǎng)站開發(fā)制作服務。插件(Plug-in)是一種遵循一定規(guī)范的應用程序接口編寫出來的程序。其只能運行在程序規(guī)定的系統(tǒng)平臺下(可能同時支持多個平臺),而不能脫離指定的平臺單獨運行。
實現(xiàn)插件機制的兩大要素:一個是接口,另一個是反射。接口其實是一種“契約”,主程序是通過這種“契約”來約束是否存在符合我期望的對象,如果不符合就不會去加載該對象。在CodeEditor
中我們約定的接口是IExcutable
。而這種“契約”的執(zhí)行就是通過反射來達到目的,主程序中會通過反射加載約定好的Plugin文件夾下所有的DLL文件,然后遍歷這些插件并查看是否存在實現(xiàn)了IExcutable的并且可以實例化的類,如果有則創(chuàng)建該類的實例加入集合并返回集合。主程序拿到集合后會在構(gòu)造函數(shù)中加載這些插件,加載過程包括動態(tài)添加菜單、指定菜單的點擊事件,這樣完整的插件加載過程就完成了。下面通過CodeEditor
來具體看下插件的實現(xiàn)過程。
下面的圖是整個CodeEditor
的目錄結(jié)構(gòu)
第三個CodeEditorControl可以忽略,這個類庫是一個自定義的控件,是實現(xiàn)一個帶行號的文本編輯器的核心組件,但是和本文主題關系不大。主要看插件接口CodeEditorInterface和插件實現(xiàn)CodeEditorPlugins以及主程序CodeEditor。這三者的關系可以通過以下圖片來展示。
首先從主程序和插件之間的橋梁入手,就是插件的接口,在CodeEditorInterface中的接口IExcutable中有兩個約定方法,一個是GetName負責返回當前的插件名稱,用于主程序獲取并動態(tài)加載到菜單中;另一個是Excute負責獲取主程序中文本并執(zhí)行相應的操作。代碼如下:
1 public interface IExcutable2 {3 //用于主程序動態(tài)創(chuàng)建菜單4 string GetName();5 //執(zhí)行具體的文本操作6 string Excute(string text);7 }
下面是主程序加載符合“契約”的插件對象的核心代碼,主要作用就是過濾符合接口的類并實例化類的對象,加到集合中:
1 public class Common 2 { 3 /// <summary> 4 /// 加載插件 5 /// </summary> 6 /// <returns></returns> 7 public static List<IExcutable> GetPlugins() 8 { 9 List<IExcutable> implementObject = new List<IExcutable>();10 //獲取項目根目錄下的Plugins文件夾11 string dir = GetPluginsDir();12 //遍歷目標文件夾中包含dll后綴的文件13 foreach (var file in Directory.GetFiles(dir + @"\", "*.dll"))14 {15 //加載程序集16 var asm = Assembly.LoadFrom(file);17 //遍歷程序集中的類型18 foreach (var type in asm.GetTypes())19 {20 //如果是IExcutable接口21 if (type.GetInterfaces().Contains(typeof(IExcutable)))22 {23 //創(chuàng)建接口類型實例24 var IExcutable = Activator.CreateInstance(type) as IExcutable;25 if (IExcutable != null)26 {27 implementObject.Add(IExcutable);28 }29 }30 }31 }32 return implementObject;33 }34 35 /// <summary>36 /// 獲取插件目錄37 /// </summary>38 /// <returns></returns>39 static string GetPluginsDir()40 {41 string pluginDir = ConfigurationManager.AppSettings["pluginDir"];42 return pluginDir;43 }44 }
下面的代碼段主要功能是在主程序中為插件分配菜單,綁定公共事件:
1 /// <summary> 2 /// 創(chuàng)建插件公共事件 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void Plugin_Click(object sender, EventArgs e) 7 { 8 ToolStripItem item= sender as ToolStripItem; 9 if (null != item)10 {11 12 if (null != item.Tag)13 {14 IExcutable plugin = item.Tag as IExcutable;15 if (null != plugin)16 {17 CodeContent.RichText=plugin.Excute(CodeContent.RichText);18 }19 }20 }21 }22 23 /// <summary>24 /// 主程序加載插件25 /// </summary>26 private void LoadPlugins()27 {28 List<IExcutable> list = Common.Common.GetPlugins();29 foreach (var Iplugins in list)30 {31 ToolStripMenuItem item = new ToolStripMenuItem(Iplugins.GetName());//動態(tài)創(chuàng)建以插件菜單32 item.Name = Iplugins.GetName();33 item.Click += new EventHandler(Plugin_Click);//綁定公共事件34 item.Tag = Iplugins;35 this.Plugins.DropDownItems.Add(item);36 }37 }
其中的GetPlugins方法就是遍歷指定目錄下的DLL文件,并把符合接口約定的對象加入集合返回給主程序。而GetPluginsDir方法是獲取插件的存儲位置,主要是在配置文件中讀取插件目錄。
1 <?xml version="1.0" encoding="utf-8"?> 2 <configuration> 3 <startup> 4 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/> 5 </startup> 6 <appSettings> 7 <!--配置加載插件目錄--> 8 <add key="pluginDir" value="CodeEditorPlugins"/> 9 </appSettings>10 </configuration>
實現(xiàn)效果如圖:
轉(zhuǎn)換前的文本,F(xiàn)ormat的作用是把所有的小寫字母轉(zhuǎn)為大寫。
轉(zhuǎn)換后的文本。
這個迷你編輯器是之前的一個小程序,整理代碼的時候發(fā)現(xiàn)的,突然想改造一下使其更符合我的使用要求,就順便加了個插件機制。插件機制是一種良好的軟件設計思想,可以在不修改主程序的情況下擴展主程序的功能,有時候一款軟件的插件功能要比主程序自帶的功能要強大得多。應用插件機制要注意幾點:
定義接口,也就是主程序與插件的“契約”
應用反射,通過反射來加載符合接口的類,然后創(chuàng)建該類的對象調(diào)用接口方法
另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。
新聞名稱:基于接口的插件機制-創(chuàng)新互聯(lián)
文章起源:http://www.rwnh.cn/article18/ccsggp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設、企業(yè)網(wǎng)站制作、服務器托管、網(wǎng)站改版、外貿(mào)建站、小程序開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容