实战基础技能(14)--------WPF之插件开发

一:解决方案管理器截图

二:简单功能说明

IMsg定义了一个接口,MYPlugin1实现接口功能,”插件式开发“实现程序运行时再调用非本身引用的dll文件,调用该dll的方法实现功能

三:IMsg、MYPlugin1(class1和class2)和插件式开发的代码

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

namespace IMsg
{
    ///<summary>
/// 这是插件必须实现的接口,也是主程序与插件通信的唯一接口
/// 换句话说,主程序只认识插件里的这些方法
///</summary>
    public interface IMsgPlug
    {
        void OnShowDlg();
        string OnShowInfo();
    }
}
using System;
using System.Collections.Generic;
using System.Text;
using IMsg;
namespace MYPlugin1
{
    public class myConsole : IMsgPlug
    {
        #region IMsgPlug 成员
        public void OnShowDlg()
        {
            Console.WriteLine("控制台调用插件的OnShowDlg方法");
        }
        public string OnShowInfo()
        {
            return "myConsole";
        }
        #endregion
    }
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using IMsg;
namespace MYPlugin1
{
    public class MYDlg : Form, IMsgPlug
    {
        #region IMsgPlug 成员

        public void OnShowDlg()
        {
            this.Text = "插件子窗体";
            this.ShowDialog();//调用Form的ShowDialog,显示窗体
        }
        public string OnShowInfo()
        {
            return "MyDlg";
        }
        #endregion
    }
}
程序的主要、重要代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections;
using System.IO;
using System.Reflection;

namespace 插件式开发
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
         // 存放插件的集合
         private ArrayList plugins =new ArrayList();

        public MainWindow()
        {
            InitializeComponent();
        }
        ///<summary>
        /// 载入所有插件
        ///</summary>
        private void LoadAllPlugs()
        {
            //获取插件目录(plugins)下所有文件
           // string[] files = Directory.GetFiles(Application.ResourceAssembly + @"\plugins");
            //string str6 = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;//获得到debug的文件夹
            //str6 = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;//获得到exe文件
            //str6 = System.Environment.CurrentDirectory;//获得到debug的文件夹
            //str6 = System.IO.Directory.GetCurrentDirectory();//获得到debug的文件夹
            //str6 = System.AppDomain.CurrentDomain.BaseDirectory;//获得到debug的文件夹
            //str6 = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;//获得到debug的文件夹
            //str6 = System.Windows.Forms.Application.StartupPath;//获得到debug的文件夹
             //string[] files = Directory.GetFiles(AppDomain.CurrentDomain +"plugins");

            string[] files = Directory.GetFiles(@"E:\练习代码\IMsg\插件式开发\plugins");//得到dll文件的存放路径
            foreach (string file in files)
            {
                if (file.ToUpper().EndsWith(".DLL"))//如果文件以dll结尾
                {
                    try
                    {
                        //载入dll
                        Assembly ab = Assembly.LoadFrom(file);//一个程序集合
                        Type[] types = ab.GetTypes();//类型数组
                        foreach (Type t in types)
                        {
                            //如果某些类实现了预定义的IMsg.IMsgPlug接口,则认为该类适配与主程序(是主程序的插件)
                            if (t.GetInterface("IMsgPlug") != null)
                            {
                                plugins.Add(ab.CreateInstance(t.FullName));//将实例化的dll加入到泛型集合中
                                lstWays.Items.Add(t.FullName);//显示在listbox中
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
        }

        //窗体载入事件
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            LoadAllPlugs();
        }

        //调用插件的方法
        private void btnGetIn_Click(object sender, RoutedEventArgs e)
        {
            if (this.lstWays.SelectedIndex == -1) return;
            object selObj = this.plugins[this.lstWays.SelectedIndex];
            Type t = selObj.GetType();
            MethodInfo OnShowDlg = t.GetMethod("OnShowDlg");//得到dll文件的中的方法
            MethodInfo OnShowInfo = t.GetMethod("OnShowInfo");//得到dll文件的中的方法

            OnShowDlg.Invoke(selObj, null);//方法调用参数
            object returnValue = OnShowInfo.Invoke(selObj, null);
        }
    }
}

四:后记

提起插件式,我们首先想到的是firefox, 用过firefox的人都知道它是一个插件式程序。当一个功能需要,完全可以从网上下载一个插件后,重启后,就能使用。这个功能给我们带来许多的方便之处,这就是插件式程序的好处。
  插件的本质在于不修改程序主体(平台)的情况下对软件功能进行拓展与加强,当插件的接口公开后,任何公司或个人都可以制作自己的插件来解决一些操作上的不便或增加新功能,也就是真正意义上实现“即插即用”软件开发。
  平台+插件软件结构是将一个待开发的目标软件分为两部分,一部分为软件的主体或框架,可定义为平台,这是预先编译后的程序。另一部分为功能或补充模块,可定义为插件。这个就是后来要进行安装的插件程序。
  假设你的程序已经部署在用户的计算机上,并且能够正常运行了。但是有一天,用户打来电话——他们需要增加新的功能。确定了用户的需求后,你竟然发现原有的软件架构已经无法胜任新增任务的需求——你需要重新设计这个应用了!但问题是,就算你又用了一个开发周期完成了用户需要的应用,切不能保证用户的需求不会再次变更。也就是说,需求蔓延的可能性依然存在。因此,这种情况下插件架构更能显示出它的优越性。
  可以这么说,用它可以带来方便的地方,而且开发它,也很简单。而且这样的主程序根本就不需要改动。需要插件时,拿来就能用,插件更新时,也只需更新这个插件即可。
  从程序开发这角度,一般是先开发主程序,决定哪些功能由主程序来完成,然后再建立接口,申明接口的内容,这些内容决定着插件功能的扩展及方向的。这些都是有主程序开发者预先准备好的。插件开发者,从主程序开发者那里得到接口的内容,并书写继承这些接口的类,来完成具体的功能。

时间: 2024-08-04 16:27:40

实战基础技能(14)--------WPF之插件开发的相关文章

实战基础技能(07)--------WPF的登录界面的排版

一:截图 二:XAML代码 <Window x:Class="wpf练习.登录窗体" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="登录窗体" Height="200" Width="

实战基础技能(08)--------MVVM模式中WPF数据的完全绑定

一:截图,描述:将后台代码的姓名.年龄绑定到文本框,单击”增加年龄“--年龄自+1,单击”显示年龄“--弹出年龄的显示对话框,实现了从文本框修改年龄和后台更改年龄并显示到文本框 运行结果和解决方案管理截图如下: 二:person类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; namespace 完全数据绑定 {

实战基础技能(02)-----------类,属性,构造函数和方法打死都要快速区分

一:做项目时经常会看见很对自定义的类,一定要快速的识别才能正确的理解项目代码 二:区分 类:很好区分,有Class修饰 方法:有返回值的描述,新的方法名 构造函数:没有返回值,有类名 属性:主要是get 和set标志,可能会有自定义的类型有一定的迷惑性 实战基础技能(02)-----------类,属性,构造函数和方法打死都要快速区分,布布扣,bubuko.com

实战基础技能(06)--------object sender C#有个毛作用

button1_Click(object sender,EventHandler e) { Button button=(Button)sender; button.Text="text property has been changed at its event"; } object 是事件的激发控件,或叫事件源:具体我们可以用MessageBox.Show(sender.ToString())直接输出,我们可以直接看到; 如果一个按钮button1,我点击这个按钮﹕sender就是

实战基础技能(07)--------DEV控件的Gridview小技巧总结

1.设置Gridview控件的某列不可编辑 this.gridData.gridView1.Columns["change_date"].OptionsColumn.AllowEdit = false; 字段:change_date是数据库中字段,是绑定到gridview上的. 2.设置Gridview控件整体不可编辑 this.gridData.IsEnableEdit = false; 3.设置Gridview控件,列头不可排序 this.gridDataDetail.gridVi

实战基础技能(24)--------Moss的使用

实战基础技能(23)--------SQL Server 2008 无法保存表的更改

MS SQL Server 2008 在建完表后,如果要重新设计表,如修改字段长度,就会提示:“当用户在在SQL Server 2008企业管理器中更改表结构时,必须要先删除原来的表,然后重新创建新表,才能完成表的更改,如果强行更改会出现以下提示:不允许保存更改.您所做的更改要求删除并重新创建以下表.您对无法重新创建的标进行了更改或者启用了“阻止保存要求重新创建表的更改”选项”.如才能直接保存对表的更改?打开Microsoft SQL Server Management Studio 菜单栏 “

实战基础技能(20)--------发布WebService到IIS和调用WebService

一:在项目上右键单击,选择发布,如图 二:可以单击重命名,自定义网站的名字,发布方式为:文件系统,目标路径为要发布的文件的位置,它需要放到IIS的目录下面的 三:打开IIS管理器,右键单击网站,添加网站 四:将刚发布的文件复制到IIS的默认路径下,选择为物理路径,更改默认端口 五:双击默认文档,设置WebService的默认打开文档,这个为接口的入口 六:winform程序调用WebService,双击生成的exe文件,就实现了调用WebService(winform程序见上一篇文章)

实战基础技能(11)--------SQL中ISNULL的使用

在敲写相关sql语句时,我们经常会遇到一些空的字符串或者是字段,这就给我们对数据库造成一定的麻烦,系统经常会提示“某值null不能转换”“插入的值不能为空”等等诸如此类的提示,isnull函数会帮助你搞定这些小菜. Isnull 函数主要作用是将为空的值替换为指定值,如果不为空返回检查类型的返回值,isnull的语法: Isnull (check_expression , replacement_value) 参数check_expression ,是待检查是否为空的表达式,参数replacem