C# 动态加载插件的实现

来源:互联网 发布:ajax跨域php 编辑:程序博客网 时间:2024/05/22 05:05

花了半天时间,终于弄懂了C#如何现实动态加载插件的。就像photoshop一样只要在plugin里面丢几个dll就可以多一个滤镜。

总体思路必将简单

1.必须定义公共接口规范,说白点就是主程序在调用插件时会用到方法、属性、函数等等。有点类似于组织架构的岗位名称,岗位是固定的,任职要求(参数)也是固定的,只是人不一样而已。

实现方法:

新建一个类库

namespace MainPlug

{

    public interface IMainPlug

    {

        void strat(string buttonname);

        string F();

    }

}

完了F5生产DLL

2.做插件,也很简单

新建一个类库,添加刚刚生成的DLL,本例为MainPlug.DLL

 

using System;

using System.Text;

using MainPlug;

using System.Windows.Forms;

namespace Plug1

{

    public class myplug1 : Form, IMainPlug

    {

        public void strat(string buttonname)

        {

            Form f1 = new Form();

            Button b1 = new Button();

            b1.Text = buttonname;

            f1.Controls.Add(b1);

            b1.Top = 10;

            b1.Left = 10;

            f1.ShowDialog();

         

        }

        public string F()

        {

            return "this is F";

        }

    }

}

小窍门:

C 动态加载插件的实现 - 80后 - 小草
将鼠标移到IMainPlug的地方会有个小四方形出来,选择实现接口,可以自动添加接口代码,只需要在接口写内容就可以了。
F5生成Dll
 
3.主程序实现
3.1 界面
C 动态加载插件的实现 - 80后 - 小草 
3.2 思路
将第2步生产的Dll放到主程序运行目录下新建的  plugins  里面
 
点击装载(button1)会历遍目录中所有Dll,然后在Dll中历遍所有接口,如果符合的话,加入  "ArrayList plugins" 里面,并在listbox中显示
点击调用,则调用插件的方法。
注意:
MethodInfo.Invoke(selObj, new object[] { "按钮名字" }),  new object[] { "按钮名字" }  为插件方法的参数,只需要按参数顺序加入即可。
 
 
3.3  完整代码

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.Collections;

using System.Reflection;

 

namespace plugTest

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        ArrayList plugins = new ArrayList();

        private void button1_Click(object sender, EventArgs e)

        {

            string[] files = Directory.GetFiles(Application.StartupPath + "\\plugins");

            //将所有plugin文件夹下面的文件路径读取到files里面

            foreach (string file in files)

            {

                if (file.ToUpper().EndsWith(".DLL"))//将文件名转换为大写,如果后缀为".DLL"则为插件,执行下面语句

                {

                    Assembly ab = Assembly.LoadFile(file);//可以将assembly视为一个程序集的类型,通过loadfile将其实例化

                    Type[] types = ab.GetTypes();//获取程序集中程序的类型

                    foreach (Type t in types)

                    {

                        if (t.GetInterface("IMainPlug") != null)//搜索带有指定接口的插件

                        {

                            plugins.Add(ab.CreateInstance(t.FullName));//将插件装入plugins集合

                            listBox1.Items.Add(Full.Name );//在列表显示名字

                        }

                    }

                }

            }

        }

 

        private void button2_Click(object sender, EventArgs e)

        {

            if (listBox1.SelectedIndex == -1) return;//如果ListBox为空则返回

            object selObj = this.plugins[listBox1.SelectedIndex];//将插件定义为一个对象

            Type t = selObj.GetType();//获取插件的类型

            MethodInfo Start = t.GetMethod("strat");//搜索指定方法,并将方法赋值给指定的实例

            MethodInfo F = t.GetMethod("F");

 

            Start.Invoke(selObj, new object[] { "按钮名字" });//实例化对象,new object[] {"按钮名字"}是参数集合

 

            textBox1.Text = F.Invoke(selObj, null).ToString();//实例化对象

 

        }

    }

}

 
 

 

0 0
原创粉丝点击