c#插件式开发

接着上一篇文章:http://blog.csdn.net/joyhen/article/details/22905481

MEF:http://www.cnblogs.com/tcjiaan/tag/MEF/

原文:http://blog.csdn.net/jam12315/archive/2008/08/18/2791534.aspx

首先,新建一个类库,里面定义接口,这里定义两个方法,一个有返回值的,一个无返回值的。

using System;  
using System.Collections.Generic;  
using System.Text;  
  
namespace IMsg {  
    ///<summary>  
    /// 这是插件必须实现的接口,也是主程序与插件通信的唯一接口  
    /// 换句话说,主程序只认识插件里的这些方法  
    ///</summary>  
    publicinterface IMsgPlug {  void OnShowDlg();  string OnShowInfo();  
    }  
}  
将上面的类库生成IMsg.dll, 新建一个类库MYPlugin1,添加刚出的引用,分别新建两个类来实现IMsg中定义的接口。
using System;  
using System.Collections.Generic;  
using System.Text;  
using IMsg;  
namespace MYPlugin1 {  
    publicclass myConsole: IMsgPlug {#region IMsgPlug成员publicvoid OnShowDlg() {  
            Console.WriteLine("控制台调用插件的OnShowDlg方法");  
        }  
        publicstring OnShowInfo() {  
            return "myConsole";  
        }#endregion  
    }  
}  
  
using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Windows.Forms;  
using IMsg;  
namespace MYPlugin1 {  
    publicclass MYDlg: Form,  
    IMsgPlug {#region IMsgPlug成员  
  
        publicvoid OnShowDlg() {  
            this.Text = "插件子窗体";  
            this.ShowDialog(); //调用Form的ShowDialog,显示窗体  
        }  
        publicstring OnShowInfo() {  
            return "MyDlg";  
        }#endregion  
    }  
}  
将上面的都生成dll, 生成目录可以设置为新建exe工程的bin目录plugins文件夹下。Plugins文件夹是新建的,专门存放插件的。 新建一个 WinForm项目来使用刚才的插件.


using System;  
using System.IO;  
using System.Linq;  
using System.Collections;  
using System.Windows.Forms;  
using System.Reflection;  
  
namespace myConsole  
{  
    public partial class Form1 : Form  
    {  
        /// <summary>  
        /// 应用程序的主入口点。  
        /// </summary>  
        [STAThread]  
        static void Main()  
        {  
            Application.EnableVisualStyles();  
            Application.SetCompatibleTextRenderingDefault(false);  
            Application.Run(new Form1());  
        }  
  
        public Form1()  
        {  
            InitializeComponent();  
        }  
  
        /// <summary>  
        /// 存放插件的集合  
        /// </summary>  
        private ArrayList plugins = new ArrayList();  
  
        //载入所有插件  
        private void btnLoadPlug_Click(object sender, EventArgs e)  
        {  
            string[] files = Directory.GetFiles(Application.StartupPath + "\plugins");  
            if (files != null)  
                this.listBox1.Items.Clear();  
  
            foreach (var f in files)  
            {  
                if (!f.ToUpper().EndsWith(".DLL"))  
                    continue;  
                try  
                {  
                    Assembly ab = Assembly.LoadFile(f);  
                    Type[] t = ab.GetTypes();  
                    foreach (var x in t)  
                    {  
                        if (x.GetInterface("IMsgPlug") != null)  
                        {  
                            plugins.Add(ab.CreateInstance(x.FullName));  
                            this.listBox1.Items.Add(x.FullName);  
                        }  
                    }  
                }  
                catch (Exception ex)  
                {  
                    MessageBox.Show(ex.Message);  
                }  
            }  
        }  
  
        //调用插件的方法  
        private void 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();  
        }  
    }  
}  

运行结果:


此方法用了反射,个人感觉效果不是很好。另外,注意dll对象的依赖,这种问题我在手写上面demo的时候发现了,首先要保证依赖文件的存在,再一个依赖文件的路径需要正确。另一点要说下,对反射后的验证可以做一些加强处理,listbox对象显示的名字可以通过给dll中对象添加特性标记,然后获取显示出来。下一节我们看看MEF的小例子。

最后想说一下,这不是正在意义上的插件式开发,请参阅微软的MEF和MAF的设计

出处:http://blog.csdn.net/joyhen/article/details/40072973

原文地址:https://www.cnblogs.com/mq0036/p/7017494.html