我们现在已经搭建了插件式的应用程序框架,接下来的工作就是要充实框架的内容,提供基本的服务,也就是Service。我想首要的任务就是提供插件的管理服务,我在前面的文章也提到了,要实现动态加载必须要知道插件寄宿在哪里,哪些要加载,哪些不加载,这些就是这篇文章要讨论的问题。
首先解决的就是插件放在什么地方,我采取的传统的方法,将插件放到应用程序所在目录下的制定目录,我会在应用程序所在的目录下创建一个文件夹,命名为Plugins。接下来的工作就是要通知哪些插件是要加载的,哪些是不需要加载的,我会将这些信息放到应用程序的配置文件中的制定配置块中,当应用程序运行的时候,就会读取配置文件,并根据获得的信息加载插件。另外我们的应用程序框架是建立在Service基础之上,所以我需要创建一个管理插件的service。
我们现在定义一个插件管理的Service接口。
using System;
using System.Collections.Generic;
using System.Text;
namespace PluginFramework
{
public interface IPluginService
{
IApplication Application { get; set; }
void AddPlugin(String pluginName, String pluginType, String Assembly, String pluginDescription);
void RemovePlugin(String pluginName);
String[] GetAllPluginNames();
Boolean Contains(String pluginName);
Boolean LoadPlugin(String pluginName);
Boolean UnLoadPlugin(String pluginName);
IPlugin GetPluginInstance(String pluginName);
void LoadAllPlugin();
}
}
PluginService要实现的目标首先是在配置文件中添加/删除要加载的插件以及相关的信息,接下来就是动态的加载插件。我们要定义几个类型:Plugin配置区块类型,Plugin元素类型,plugin元素集合类型,以便我们能够读取插件的信息。
最后我们实现PluginService:
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Configuration;
using System.Reflection;
using System.Windows.Forms;
using System.IO;
using System.Collections;
namespace PluginFramework
{
public class PluginService : IPluginService
{
private IApplication application = null;
private PluginConfigurationSection config = null;
private Dictionary<String, IPlugin> plugins = new Dictionary<string, IPlugin>();
private XmlDocument doc = new XmlDocument();
public PluginService()
{
}
public PluginService(IApplication application)
{
this.application = application;
}
IPluginService Members#region IPluginService Members
public void AddPlugin(string pluginName, string pluginType, string assembly, string pluginDescription)
{
doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
XmlNode pluginNode = doc.SelectSingleNode("/configuration/PluginSection");
XmlElement ele = doc.CreateElement("add");
XmlAttribute attr = doc.CreateAttribute("Name");
attr.Value = pluginName;
ele.SetAttributeNode(attr);
XmlAttribute attrType = doc.CreateAttribute("Type");
attrType.Value = pluginType;
ele.SetAttributeNode(attrType);
XmlAttribute attrAss = doc.CreateAttribute("Assembly");
attrAss.Value = assembly;
ele.SetAttributeNode(attrAss);
XmlAttribute attrDes = doc.CreateAttribute("Description");
attrDes.Value = pluginDescription;
ele.SetAttributeNode(attrDes);
pluginNode.AppendChild(ele);
doc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
ConfigurationManager.RefreshSection("PluginSection");
}
public void RemovePlugin(string pluginName)
{
doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
XmlNode node = doc.SelectSingleNode("/configuration/PluginSection");
foreach (XmlNode n in node.ChildNodes)
{
if (n.Attributes != null)
{
if (n.Attributes[0].Value == pluginName)
{
node.RemoveChild(n);
}
}
}
doc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
ConfigurationManager.RefreshSection("PluginSection");
}
public string[] GetAllPluginNames()
{
config = (PluginConfigurationSection)ConfigurationManager.GetSection("PluginSection");
PluginConfigurationElement pe = new PluginConfigurationElement();
ArrayList ps = new ArrayList();
for (Int32 i = 0; i < config.PluginCollection.Count; i++)
{
pe = config.PluginCollection[i];
ps.Add(pe.Name);
}
return (String[])ps.ToArray(typeof(String));
}
public bool Contains(string pluginName)
{
config = (PluginConfigurationSection)ConfigurationManager.GetSection("PluginSection");
PluginConfigurationElement pe = new PluginConfigurationElement();
List<String> ps = new List<string>();
for (Int32 i = 0; i < config.PluginCollection.Count; i++)
{
pe = config.PluginCollection[i];
ps.Add(pe.Name);
}
return ps.Contains(pluginName);
}
public bool LoadPlugin(string pluginName)
{
Boolean result = false;
config = (PluginConfigurationSection)ConfigurationManager.GetSection("PluginSection");
PluginConfigurationElement pe = new PluginConfigurationElement();
String path = Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + "\\Plugin";
try
{
for (Int32 i = 0; i < config.PluginCollection.Count; i++)
{
pe = config.PluginCollection[i];
if (pe.Name == pluginName)
{
Assembly assembly = Assembly.LoadFile(path + "\\" + pe.Assembly);
Type type = assembly.GetType(pe.Type);
IPlugin instance = (IPlugin)Activator.CreateInstance(type);
instance.Application = application;
instance.Load();
plugins[pluginName] = instance;
result = true;
break;
}
}
if (!result)
{
MessageBox.Show("Not Found the Plugin");
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
result = false;
}
return result;
}
public bool UnLoadPlugin(string pluginName)
{
Boolean result = false;
try
{
IPlugin plugin = GetPluginInstance(pluginName);
plugin.UnLoad();
result = true;
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
return result;
}
public void LoadAllPlugin()
{
PluginConfigurationElement pe = new PluginConfigurationElement();
config = (PluginConfigurationSection)ConfigurationManager.GetSection("PluginSection");
String path = Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + "\\Plugin";
try
{
for (Int32 i = 0; i < config.PluginCollection.Count; i++)
{
pe = config.PluginCollection[i];
Assembly assembly = Assembly.LoadFile(path + "\\" + pe.Assembly);
Type type = assembly.GetType(pe.Type);
IPlugin instance = (IPlugin)Activator.CreateInstance(type);
instance.Application = application;
instance.Load();
plugins[pe.Name] = instance;
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
public IApplication Application
{
get
{
return application;
}
set
{
application = value;
}
}
public IPlugin GetPluginInstance(string pluginName)
{
IPlugin plugin = null;
if (plugins.ContainsKey(pluginName))
{
plugin = plugins[pluginName];
}
return plugin;
}
#endregion
}
}
由于代码比较多,我也就不一一列举了,只把比较重要的代码列出来,其余的我会提供源代码的下载。在实现了PluginService以后,我们需要有一个地方能够使用这个Service来管理插件,我的做法是在一个菜单里添加一个项目,当用户点击这个项目的时候弹出插件管理的对话框,用户在这个对话框中选择使用那些插件,当插件被选中的时候,插件会被立即加载进来,并且记录到配置文件里,当用户下次运行应用程序的时候,插件默认会被自动的加载。
另外从现在开始我们就需要使用配置文件了,所以,我们需要给应用程序添加一个app.config文件,文件内容如下:
复制
保存
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section
name="PluginSection"
type="PluginFramework.PluginConfigurationSection, PluginFramework"
/>
</configSections>
<PluginSection>
</PluginSection>
</configuration>
样子,总体来说我们就为Plugin的管理提供了一个基本的实现,如果大家还有什么不明白的地方,可以参考我提供的源代码或者通过e-mail和我联系。
源代码下载
http://files.cnblogs.com/guanjinke/pluginsample2.rar
分享到:
相关推荐
在IT行业中,插件应用程序框架设计是一种常见的软件架构模式,它允许通过插入可扩展的模块(即插件)来增强程序的功能。Engine框架是这种设计理念的一种实现,它为开发者提供了高度灵活和可定制的解决方案。以下是对...
### 构建插件式的应用程序框架 #### 一、引言 随着软件复杂度的不断提高,传统的单体架构越来越难以适应快速变化的市场需求。插件式应用框架因其灵活性和可扩展性,在大型软件开发中逐渐受到重视。插件式应用程序...
为什么使用插件式的应用程序框架呢?我的答案就是他为应用程序的功能扩展提供的无限的想象空间。一个应用程序,无论你前期做了多少的市场调查,需求分析做的多么完美,你也只是迎合一部分人的期望,更甚,你只迎合了...
【插件式应用框架设计】是一种软件开发方法,旨在创建可扩展且易于维护的应用程序。框架和架构虽然有所关联,但并不相同。软件框架是针对特定领域的可重用设计思想和基础结构,它是软件架构的具体实现,比如ArcGIS ...
综上所述,构建插件式的应用程序框架是一项涉及多个技术领域的工作,包括设计、实现和服务管理。理解并掌握这些知识点有助于创建出强大而灵活的插件框架,满足各种应用场景的需求。在实践中,不断迭代和优化框架,使...
总之,构建插件式的应用程序框架并实现视图服务是一项具有挑战性的任务,但通过良好的设计和实施,我们可以得到一个强大且灵活的系统,能适应不断变化的业务需求和用户期望。在这个过程中,接口设计、插件注册、动态...
在.NET平台上构建插件式应用是一种常见的软件设计模式,它允许开发者将应用程序的核心功能与可扩展的模块分离,这些模块即插件。这种方式使得应用程序能够根据需求动态加载和卸载功能,增强了软件的灵活性和可维护性...
《插件式GIS应用框架的设计与实现:基于C#和AE+9.2》是一本深入探讨GIS(地理信息系统)开发技术的专业书籍,主要聚焦于使用C#编程语言和ArcGIS Engine(AE)9.2版本来构建插件式GIS应用的理论与实践。GIS是一种集成...
Z-GIS是一个企业级的通用插件式GIS应用程序框架,Z-GIS框架能够从根本上解决架构稳定性和需求多变性之间的矛盾。Z-GIS框架运行环境是Windows + ArcEngine Runtime9.3 ;或是windows + 任意版本的AO9.3。 Z-GIS...
通过深入研究这些资料,开发者不仅可以学会如何构建插件式GIS应用,还可以掌握C#和ArcGIS Engine结合的开发技巧,提升自己的GIS应用开发能力。对于GIS专业的学生、研究人员或从业人员来说,这是一个非常有价值的资源...
SpringBoot插件式开发框架是基于SpringBoot框架构建的一种创新性开发模式,旨在解决系统动态扩展和模块化管理的问题。这种框架充分利用了SpringBoot的简洁、高效特性,为开发者提供了快速构建可插拔功能的能力。下面...
QT插件管理器框架是一种基于QT库开发的插件化应用程序框架,主要目的是为了实现软件功能的模块化和可扩展性。在QT中,插件技术允许开发者将应用程序的核心功能与可选的功能组件分离,这些组件可以单独进行更新、安装...
本文通过介绍插件式GIS应用框架的设计与实现,探讨了如何利用C#和AE+9.2技术构建一个高效、灵活的GIS应用平台。通过模块化的插件设计、高性能的插件引擎以及功能完善的宿主程序,实现了GIS应用的高度可定制性和扩展...
《插件式GIS应用程序框架的设计与实现》是蒋波涛老师的一本专著,主要探讨了如何使用C#编程语言和Esri的ArcGIS Engine 9.2来构建灵活、可扩展的地理信息系统(GIS)应用。源码的提供使得读者能够深入理解书中的理论...
EngineFramework是一个具体的插件式应用程序框架示例,可能由张学宝(我不是小菜)开发,应用于基于ArcGIS Engine的应用。该框架可能包含了一系列设计话题,如如何实现插件识别、加载和通信机制,以及如何利用面向...