[经验交流] 简易插件机制的实现方法浅谈
简易插件机制的实现方法浅谈野比 著
下载例程源代码:
PluginDemo.rar
(42.54 KB)
简介
插件(Plugin),是现代软件设计的一大亮点。通过插件机制,我们的应用程序可以最大化的获得可扩展性、适应性和稳定性,而且便于软件的维护和升级。对于插件的优缺点,我不做探讨。
在本文中你将了解到如何为应用程序实现一种简单、直接的插件机制。使用此种插件机制,我们可以开发出高度可扩展的应用程序,提高程序整体水平。
结构
我们的程序可以加载不同功能的插件——可以是我们自己或其他任何人开发的——而不需要事先知道插件所完成的功能。当然,类似如何加载插件这样的基本方法程序是约定好的。
这里使用到了程序设计的一种方法:后期绑定([it]Late-Binding[/it])。
简单来说,我们要做的就是让程序在运行时动态加载保存于插件中的方法、属性等,并对其进行调用,以实现相应功能。为了管理插件,需要为插件提供一个统一的管理接口。插件与程序通过接口进行交流。
设计插件机制如下图所示:
实现
通过分析设计,我们确定按照以下方式实现插件机制:
[*]应用程序 exe 控制台程序
[*]插件接口 dll 类库
[*]插件 dll 类库
简单起见,我们的应用程序不适用 GUI 。关于 GUI 的使用,包括如何在插件中实现界面,请参考本文提供的源程序 Demo。
为了避免使用反射(Reflection)等高级概念,这里使用 System.Runtime.Remoting 命名空间中 Activator 类。
该类包含 Activator.CreateInstanceFrom() 方法,可以从任意路径的插件加载其中的功能类。只需要一句代码:
System.Activator.CreateInstanceFrom(string pluginFilePath, string pluginClassName);
该方法返回的是 ObjectHandle 类型的对象句柄,需要对其进行解包,才能直接使用。解包使用如下代码:
ObjectHandle objHandle = System.Activator.CreateInstanceFrom("..//..//plugins//pluginA.dll", "PluginA");
//解包
IPlugin plugin = objHandle.Unwrap() as IPlugin;
//解包
IPlugin plugin = objHandle.Unwrap() as IPlugin;
其中,假设我们的插件 PluginA.dll 存放于 ../plugins 目录中。解包后得到的 plugin 对象是插件功能类 PluginA的一个实例。之后对 plugin 对象的相关方法进行调用就可以使用插件了。例如,假设插件 pluginA.dll 的功能类 PluginA 包含 ShowGUI() 方法显示图形界面,则使用下面的代码对其进行调用:
plugin.ShowGUI();
这样我们就完成了一种简易的插件机制。最后 Demo 运行效果如下图:
扩展
插件也许会有和主程序交流的需求,所以我们可以为插件增加一个主程序接口 IPluginHost,其中包含了主程序的相关信息。然后在主程序(从此 IPluginHost 接口继承)加载插件时对其进行注册,这样即可在插件中对主程序进行访问。
在 插件接口.dll 中声明:
public interface IPluginHost
{
bool Register(IPlugin plugin);
}
{
bool Register(IPlugin plugin);
}
在主程序中实现此接口:
public bool Register(IPlugin plugin)
{
//对 plugin 进行操作
//对主程序进行操作
}
{
//对 plugin 进行操作
//对主程序进行操作
}
我们还需要在 IPlugin 接口中增加 Host 属性,并在插件中对其进行实现:
//IPlugin 中增加
IPluginHost Host{ get;set; }
//插件中增加
private IPluginHost pluginHost;
public IPluginHost Host
{
get { return pluginHost; }
set
{
pluginHost = value;
pluginHost.Register(this);
}
}
IPluginHost Host{ get;set; }
//插件中增加
private IPluginHost pluginHost;
public IPluginHost Host
{
get { return pluginHost; }
set
{
pluginHost = value;
pluginHost.Register(this);
}
}
参考文献
1. Mike Pagel [德国], [it]Enabling Your Application to Become a Plugin Host[/it]
2. Shoki [印度], [it]Plugin Architecture using C#[/it]
3. Roy Osherove [以色列], [it]Add run-time functionality to your application by providing a plug-in mechanism[/it]
[[it] 本帖最后由 野比 于 2009-3-17 22:35 编辑 [/it]]