码迷,mamicode.com
首页 > Windows程序 > 详细

浅析c#插件程序研究

时间:2015-10-31 13:07:44      阅读:296      评论:0      收藏:0      [点我收藏+]

标签:

   c#语言可以开发许多程序插件,其中包括浏览器插件等等。

by the way,说起插件,技术分享

我们首先想到的是遨游浏览器,firefox, 用过firefox的人都知道它是一个插件式程序。当一个功能需要,完全可以从网上下载一个插件后,重启后,就能使用。这个功能给我们带来许多的方便之处,这就是插件式程序的好处。

  插件的本质在于不修改程序主体(平台)的情况下对软件功能进行拓展与加强,当插件的接口公开后,任何公司或个人都可以制作自己的插件来解决一些操作上的不便或增加新功能,也就是真正意义上实现“即插即用”软件开发。

  平台+插件软件结构是将一个待开发的目标软件分为两部分,一部分为软件的主体或框架,可定义为平台,这是预先编译后的程序。另一部分为功能或补充模块,可定义为插件。这个就是后来要进行安装的插件程序。

  假设你的程序已经部署在用户的计算机上,并且能够正常运行了。但是有一天,用户打来电话——他们需要增加新的功能。确定了用户的需求后,你竟然发现原有的软件架构已经无法胜任新增任务的需求——你需要重新设计这个应用了!但问题是,就算你又用了一个开发周期完成了用户需要的应用,切不能保证用户的需求不会再次变更。也就是说,需求蔓延的可能性依然存在。因此,这种情况下插件架构更能显示出它的优越性。

  可以这么说,用它可以带来方便的地方,而且开发它,也很简单。而且这样的主程序根本就不需要改动。需要插件时,拿来就能用,插件更新时,也只需更新这个插件即可。

  从程序开发这角度,一般是先开发主程序,决定哪些功能由主程序来完成,然后再建立接口,申明接口的内容,这些内容决定着插件功能的扩展及方向的。这些都是有主程序开发者预先准备好的。插件开发者,从主程序开发者那里得到接口的内容,并书写继承这些接口的类,来完成具体的功能。

  下面来写个例子,这个例子没实际意义,纯属学习思想。例子是网上的经过自己改造的,发现别人某些地方不合理。

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

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

namespace  IMsg
{
/// <summary>
///  这是插件必须实现的接口,也是主程序与插件通信的唯一接口
///  换句话说,主程序只认识插件里的这些方法
/// </summary>
public interface  IMsgPlug
{
  void  OnShowDlg();
  string  OnShowInfo();
}
}

  将上面的类库生成IMsg.dll, 新建一个类库MYPlugin1,添加刚出的引用,分别新建两个类来实现IMsg中定义的接口。

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
}
}

  将上面的都生成dll, 生成目录可以设置为新建exe工程的bin目录plugins文件夹下。Plugins文件夹是新建的,专门存放插件的。 新建一个 WinForm项目来使用刚才的插件.图:

技术分享


using  System;
using  System.Collections.Generic;
using  System.ComponentModel;
using  System.Data;
using  System.Drawing;
using  System.Text;
using  System.Windows.Forms;

using  System.Collections;
using  System.IO;
using  System.Reflection;
namespace  MsgBoxMain
{
public partial class  FormMain : Form
{

/// <summary>
///  存放插件的集合
/// </summary>
private  ArrayList plugins  = new  ArrayList();
public  FormMain()
{
InitializeComponent();
}

/// <summary>
///  载入所有插件
/// </summary>
private void  LoadAllPlugs()
{
// 获取插件目录(plugins)下所有文件
string [] files  =  Directory.GetFiles(Application.StartupPath  + @" \plugsins " );
foreach  ( string  file  in  files)
{
if  (file.ToUpper().EndsWith( " .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));
listBox1.Items.Add(t.FullName);
}
}
}
catch  (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}

private void  btnLoadPlug_Click( object  sender, EventArgs e)
{
LoadAllPlugs();
}

// 调用插件的方法
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();

}
}
}

  运行结果:

技术分享

下面讨论插件代码:




if (itemStr =="myConsole")
{//调用存储在动态数组plugins里面的插件对象的OnShowInfo方法
string msgInfo = ((IMsgPlug)plugins[ListItems.SelectedIndex]).OnShowInfo();
MessageBox.Show(msgInfo, "MYPlugin1", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
elseif (itemStr =="MYDlg")//调用存储在动态数组plugins里面的插件对象的OnShowDlg方法
{
((IMsgPlug)plugins[ListItems.SelectedIndex]).OnShowDlg();
}

  我认为既然是插件,就应该是动态加载的,客户端肯定不能判断 itemStr, 因为实现接口的类是不可预料的,因此主程序不应该添加对IMsg的引用,也不应该在客户端实例化插件对象,因为插件开发的初衷是为了以后更新的时候不更改主程序,只提供对应的dll 下载,就可以直接使用了,以前的接口都定义好了,新的实现类也就是不可预料的,因此不能在主程序实例化实现接口的类,这样违背了插件的初衷。

end


浅析c#插件程序研究

标签:

原文地址:http://my.oschina.net/bigfool007139/blog/524276

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!