c#插件式开发1

接着上一篇文章: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项目来使用刚才的插件.

c#插件式开发1_第1张图片

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();
        }
    }
}


运行结果:

c#插件式开发1_第2张图片

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

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

你可能感兴趣的:(assembly,invoke,MethodInfo,LoadFrom)