zoukankan      html  css  js  c++  java
  • 构建插件式的应用程序框架(五)-管理插件

    我们现在已经搭建了插件式的应用程序框架,接下来的工作就是要充实框架的内容,提供基本的服务,也就是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和我联系。

    源代码下载
    https://files.cnblogs.com/guanjinke/pluginsample2.rar
  • 相关阅读:
    读写分离
    java并发集合知识点(二)
    jdbc框架有很多,包括spring jdbc
    多线程,势必涉及到共享对象读写问题
    &lt;xliff:g&gt;标签
    租赁市场的上海方(浦东/张江)
    HDU 3488Tour(流的最小费用网络流)
    sql使用存储过程和交易
    状态压缩动态规划 -- 骨牌
    Android-2手机应用程序,短信应用
  • 原文地址:https://www.cnblogs.com/lzhdim/p/1368760.html
Copyright © 2011-2022 走看看