c# 插件式程序示例

插件的好处不用多说,只要接口一样,可以任意更换表现形式。

步骤如下:

1. 新建一个类库工程MyPlug。

  默认创建Class1.cs文件,此类用于继承接口,并处理接口方法。

  a. 在该工程中新建类Iplugin,并定义接口,代码如下:

namespace MyPlug
{
    public interface Iplugin
    {
        void OnShowDlg(int No);//No表示要显示几号窗口
        string OnShowInfo();
    }
}

  b.在该工程中新建两个窗体,Form1,Form2。界面如下

     Form1                                                Form2

      

  c. 在刚才的Class1.cs中继承上述接口,并实现方法

namespace MyPlug
{
    public class Class1 : Iplugin
    {
        public void OnShowDlg(int No)
        {
            Form form;
            switch(No)    
            {
                case 2:
                    form = new Form2();
                    break;
                default:
                    form = new Form1();            
                    break;
            }
            form.ShowDialog();
        }
        public string OnShowInfo()
        {
            return "sylf-form:My";
        }
    }
}

  d. 生成解决方案,获得动态链接库dll。后续会修改dll的输出路径


2. 在该解决方案中新建一个form窗体工程plugDemo

  a.新建一个类 PluginLoader,专门处理动态链接库的加载和反射获取dll的实例:

(记得把刚才类库的输出路径改成现在这个窗体工程的Debug的plugin目录,方法就是右键上述类库的工程,选择属性,在生成选项卡的输出部分选择输出路径为这个窗体工程的Debug的plugin目录,就可以了。

或者把上述类库生成的dll手动拷贝到这个窗体工程的Debug的plugin目录,也是可以的。)

namespace plugDemo
{
    public static class PluginLoader
    {
        public static ArrayList plugins = new ArrayList();

        /// <summary>
        /// 判断DLL中是否继承了Iplugin接口
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        private static bool IsValidPlugin(Type t)
        {
            bool ret = false;
            Type[] interfaces = t.GetInterfaces();
            foreach (Type item in interfaces)
            {
                if (item.FullName.IndexOf( "Iplugin")>=0)
                {
                    ret = true;
                    break;
                }
            }
            return ret;
        }

        /// <summary>
        /// 加载插件,这里是在程序的Debug的plugin目录中搜索插件
        /// </summary>
        public static void LoadAllPlugins()
        {
            string[] files = Directory.GetFiles(Application.StartupPath + "\\plugin\\");
            foreach (string file in files)
            {
                string ext = file.Substring(file.LastIndexOf("."));
                if (ext != ".dll")
                    continue;
                try
                {
                    //加载插件的动态链接库
                    Assembly tmp = Assembly.LoadFile(file);
                    Type[] types = tmp.GetTypes();
                    foreach (Type t in types)
                    {
                        if (IsValidPlugin(t))//这两个if的功能是一样的
                        //if (t.GetInterface("Iplugin") != null)//判断该dll是否继承了Iplugin接口
                        {// 通过反射实例化
                            plugins.Add(tmp.CreateInstance(t.FullName));
                        }
                    }
                }
                catch (Exception err)
                {                    
                    throw err;
                }
            }
        }
    }
}

  b. 定义该工程的窗口界面如下:

  c. 响应按钮“载入插件”点击事件

namespace plugDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            textBox_FormNo.Text = "1";
            label_Error.Text = "";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (Convert.ToInt32(textBox_FormNo.Text)>2 && Convert.ToInt32(textBox_FormNo.Text)<1)
            {
                label_Error.Text = "输入的窗口号不正确,强制为1号窗口";
                textBox_FormNo.Text = "1";
            }
            PluginLoader.LoadAllPlugins();
            if (PluginLoader.plugins.Count>0)
            {
                object obj = PluginLoader.plugins[0];
                Type t = obj.GetType();<span style="color:#cc33cc;">
                MethodInfo OnShowDlg = t.GetMethod("OnShowDlg");<span style="color:#000000;">//获取dll中的方法名</span></span><span style="color:#cc33cc;">
                OnShowDlg.Invoke(obj, new object[] { Convert.ToInt32(textBox_FormNo.Text) });</span>
            }
        }

    }
}

  d. 至此,生成解决方案就可以运行了。


3. 说明
   OnShowDlg如果没有参数,就是OnShowDlg.Invoke(obj,null);

                      如果有参数记得要传参数。如上面的示例,参数是int,换成Invoke的表达方式就好了。
           



  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值