在網上找了下外掛程式式編程的資料,這裡自己先借鑒下別人的,同時發現有自己的看法,不過由於本人水平有限,不一定有參考價值,寫出來一方面是為了總結自己,以求提高,另一方面也希望各為朋友看到我的不足,給我提出寶貴意見。
什麼是外掛程式式編程
提起外掛程式式,我們首先想到的是firefox,用過firefox的人都知道它是一個外掛程式式程式。當一個功能需要,完全可以從網上下載一個外掛程式後,重啟後,就能使用。這個功能給我們帶來許多的方便之處,這就是外掛程式式程式的好處。
外掛程式的本質在於不修改程式主體(平台)的情況下對軟體功能進行拓展與加強,當外掛程式的介面公開後,任何公司或個人都可以製作自己的外掛程式來解決一些操作上的不便或增加新功能,也就是真正意義上實現“隨插即用”軟體開發。
平台+外掛程式軟體結構是將一個待開發的目標軟體分為兩部分,一部分為軟體的主體或架構,可定義為平台,這是預先編譯後的程式。另一部分為功能或補充模組,可定義為外掛程式。這個就是後來要進行安裝的外掛程式程式。
假設你的程式已經部署在使用者的電腦上,並且能夠正常運行了。但是有一天,使用者打來電話——他們需要增加新的功能。確定了使用者的需求後,你竟然發現原有的軟體架構已經無法勝任新增任務的需求——你需要重新設計這個應用了!但問題是,就算你又用了一個開發週期完成了使用者需要的應用,切不能保證使用者的需求不會再次變更。也就是說,需求蔓延的可能性依然存在。因此,這種情況下外掛程式架構更能顯示出它的優越性。
可以這麼說,用它可以帶來方便的地方,而且開發它,也很簡單。而且這樣的主程式根本就不需要改動。需要外掛程式時,拿來就能用,外掛程式更新時,也只需更新這個外掛程式即可。
從程式開發這角度,一般是先開發主程式,決定哪些功能由主程式來完成,然後再建立介面,申明介面的內容,這些內容決定著外掛程式功能的擴充,及方向的。這些都是有主程式開發人員預先準備好的。外掛程式開發人員,從主程式開發人員那裡得到介面的內容,並書寫繼承這些介面的類,來完成具體的功能。
下面來寫個例子,這個例子沒實際意義,純屬學習思想。例子是網上的經過自己改造的,發現別人某些地方不合理。
首先,建立一個類庫,裡面定義介面,這裡定義兩個方法,一個有傳回值的,一個無傳回值的。
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace IMsg{
- /// <summary>
- /// 這是外掛程式必須實現的介面,也是主程式與外掛程式通訊的唯一介面
- /// 換句話說,主程式只認識外掛程式裡的這些方法
- /// </summary> public interface IMsgPlug
- {
- void OnShowDlg();
- string OnShowInfo();
- }}
將上面的類庫產生IMsg.dll,建立一個類庫MYPlugin1,添加剛出的引用,分別建立兩個類來實現IMsg中定義的介面。
- using System;
- using System.Collections.Generic;using System.Text;using IMsg;
- namespace MYPlugin1{
- public class myConsole : IMsgPlug
- {
- #region IMsgPlug 成員
- public void OnShowDlg()
- {
- Console.WriteLine("控制台調用外掛程式的OnShowDlg方法");
- }
- public string OnShowInfo()
- { return "myConsole";
- } #endregion
- }}
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Windows.Forms;
- using IMsg;namespace MYPlugin1{
- public class MYDlg:Form,IMsgPlug
- { #region IMsgPlug 成員
- public void OnShowDlg()
- {
- this.Text = "外掛程式子表單";
- this.ShowDialog();
- //調用Form的ShowDialog,顯示表單 }
- public string OnShowInfo()
- { return "MyDlg";
- } #endregion
- }}
將上面的都產生dll,組建目錄可以設定為建立exe工程的bin目錄plugins檔案夾下。Plugins檔案夾是建立的,專門存放外掛程式的。 建立一個 WinForm項目,來使用剛才的外掛程式.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using System.Reflection;
namespace MsgBoxMain
{
publicpartialclass FormMain : Form
{
///<summary>
/// 存放外掛程式的集合
///</summary>
private ArrayList plugins =new ArrayList();
public FormMain()
{
InitializeComponent();
}
///<summary>
/// 載入所有外掛程式
///</summary>
privatevoid LoadAllPlugs()
{
//擷取外掛程式目錄(plugins)下所有檔案
string[] files = Directory.GetFiles(Application.StartupPath +@"\plugsins");
foreach (string file in files)
{
if (file.ToUpper().EndsWith(".DLL"))
{
try
{
//載入dll
Assembly ab = Assembly.LoadFrom(file);
Type[] types = ab.GetTypes();
foreach (Type t in types)
{
//如果某些類實現了預定義的IMsg.IMsgPlug介面,則認為該類適配與主程式(是主程式的外掛程式)
if (t.GetInterface("IMsgPlug")!=null)
{
plugins.Add(ab.CreateInstance(t.FullName));
listBox1.Items.Add(t.FullName);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
privatevoid btnLoadPlug_Click(object sender, EventArgs e)
{
LoadAllPlugs();
}
//調用外掛程式的方法
privatevoid btnExecute_Click(object sender, EventArgs e)
{
if (this.listBox1.SelectedIndex ==-1) return;
object selObj =this.plugins[this.listBox1.SelectedIndex];
Type t = selObj.GetType();
MethodInfo OnShowDlg = t.GetMethod("OnShowDlg");
MethodInfo OnShowInfo = t.GetMethod("OnShowInfo");
OnShowDlg.Invoke(selObj, null);
object returnValue = OnShowInfo.Invoke(selObj, null);
this.lblMsg.Text = returnValue.ToString();
}
}
}
運行結果:
這裡與網上那位原創的仁兄的看法不同(原文連結http://blog.csdn.net/jam12315/archive/2008/08/18/2791534.aspx),可供大家討論。
原文有這樣的一段:
if (itemStr == "myConsole")
{ //調用儲存在動態數組plugins裡面的外掛程式對象的OnShowInfo方法
string msgInfo = ((IMsgPlug)plugins[ListItems.SelectedIndex]).OnShowInfo();
MessageBox.Show(msgInfo, "MYPlugin1", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else if (itemStr == "MYDlg")//調用儲存在動態數組plugins裡面的外掛程式對象的OnShowDlg方法
{
((IMsgPlug)plugins[ListItems.SelectedIndex]).OnShowDlg();
}
我認為既然是外掛程式,就應該是動態載入的,用戶端肯定不能判斷 itemStr,因為實現介面的類是不可預料的,因此主程式不應該添加對IMsg的引用,也不應該在用戶端執行個體化外掛程式對象,因為外掛程式開發的初衷是為了以後更新的時候不更改主程式,只提供對應的dll 下載,就可以直接使用了,以前的介面都定義好了,新的實作類別也就是不可預料的,因此不能在主程式執行個體化實現介面的類,這樣違背了外掛程式的初衷。
原文連結:http://www.cnblogs.com/sndnnlfhvk/archive/2011/06/02/2067713.html