C#插件编程(基础)

最近也研究了下插件编程,网上的例子太少,而且不适合初学者。这里专门做了个简单易懂的例子,供大家学习,程序如有问题还望跟帖予以指教。

       程序界面运行如下:

转:C插件编程(基础) - 木乐 - 木乐的博客

//==============================================================

首先,我们要定义一个插件接口,接口规范了插件内部类的程序结构,应实现的字段,属性,方法,事件。

using System; using System.Collections.Generic; using System.Text;

namespace IMsg {   //这是插件必须要实现的接口,也是主程序与插件通信的唯一接口,     //换句话说,主程序只认识插件里的这些方法     public interface IMsgPlug     {         void OnShowDlg();         string OnShowInfo();     } }

再者,需要实现接口在主程序内部的处理过程,包括载入插件,获取插件内部的被接口规范了的字段,属性,方法,事件。

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using System.Reflection; using System.Collections; using IMsg;

namespace MsgBoxMain {     public partial class FormMain : Form     {         public ArrayList plugins = new ArrayList();         public FormMain()         {             InitializeComponent();         }         //载入插件         private void LoadAllPlugins()         {             //获取指定插件目录下的所有文件的文件名             string[] files = Directory.GetFiles(Application.StartupPath + @"\plugins");             //遍历该文件名集合             foreach (string file in files)             {   //检索出文件名以.dll结束的文件                 if (file.Substring(file.LastIndexOf(".")) == ".dll")                 {                     try                     {   //载入dll                         Assembly ab = Assembly.LoadFile(file);                         //获得载入的dll中的所有类                         Type[] tempTs = ab.GetTypes();                        //遍历该类集合                         foreach (Type tp in tempTs)                         {                             //如果某些类实现了预定义的IMsg.IMsgPlug接口,则认为该类适配与主程序(是主程序的插件)                             if (IsValidPlugin(tp))                             {   //实例化该类,并将对象装入动态数组plugins                                 plugins.Add(ab.CreateInstance(tp.FullName));                                 //将该类型名载入列表框内                                 ListItems.Items.Add(tp.Name.ToString());                             }                         }                     }                     catch(Exception ex)                     {                         MessageBox.Show(ex.ToString(), "加载插件出错", MessageBoxButtons.OK, MessageBoxIcon.Error);                     }                 }             }         }         //判断模块的类是否满足预定义接口         private bool IsValidPlugin(Type t)         {             bool ret = false;             Type[] interfaces = t.GetInterfaces();             foreach (Type theInterface in interfaces)             {                 if (theInterface.FullName == "IMsg.IMsgPlug")                 {                     ret = true;                     break;                 }             }             return ret;         }        //调用插件内的方法         private void button2_Click(object sender, EventArgs e)         {  
           //获取列表框内被选择的项             string itemStr = ListItems.SelectedItem.ToString();             if(ListItems.SelectedIndex >= 0)             {                 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();                 }             }             else                 MessageBox.Show("请先选择列表框里的插件项", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);         }

        private void button1_Click(object sender, EventArgs e)         {             try             {   //载入插件                 LoadAllPlugins();             }             catch (Exception ex)             {                 MessageBox.Show(ex.ToString());             }         }     } }

最后,编写插件类库,实现接口的属性,方法,事件。

//程序集(dll)内部的一个类1,该类实现了插件接口

using System; using System.Collections.Generic; using System.Text; using IMsg;

namespace MYPlugin1 {  //实现插件接口     public class myConsole : IMsgPlug     {           public void OnShowDlg() {}         public string OnShowInfo()         {             return "调用了插件1的OnShowInfo方法!";         }     } }

//程序集(dll)内部的一个类2,该类实现了也插件接口

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using IMsg;

namespace MYPlugin1 {   //实现插件接口     public partial class MYDlg : Form, IMsgPlug     {         public MYDlg()         {             InitializeComponent();         }

        //=============================================         public string OnShowInfo() { return null; }         public void OnShowDlg()         {             this.Show();         }         //=============================================     } }

总结: 通过反射以及接口使C#下的插件编程变得容易,我们在接口中定义的字段,属性,方法,事件是在插件里面被实现的,是在主程序里被解析的。主程序通过公共的接口访问插件

 
原文地址:https://www.cnblogs.com/movemoon/p/2769276.html