构建插件式的应用程序框架(五)----管理插件

本文介绍了一种插件式应用程序框架的设计与实现方法,包括如何管理插件、动态加载插件等内容。通过定义插件服务接口和服务实现,使得应用程序可以根据配置文件加载所需的插件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      我们现在已经搭建了插件式的应用程序框架,接下来的工作就是要充实框架的内容,提供基本的服务,也就是Service。我想首要的任务就是提供插件的管理服务,我在前面的文章也提到了,要实现动态加载必须要知道插件寄宿在哪里,哪些要加载,哪些不加载,这些就是这篇文章要讨论的问题。
       首先解决的就是插件放在什么地方,我采取的传统的方法,将插件放到应用程序所在目录下的制定目录,我会在应用程序所在的目录下创建一个文件夹,命名为Plugins。接下来的工作就是要通知哪些插件是要加载的,哪些是不需要加载的,我会将这些信息放到应用程序的配置文件中的制定配置块中,当应用程序运行的时候,就会读取配置文件,并根据获得的信息加载插件。另外我们的应用程序框架是建立在Service基础之上,所以我需要创建一个管理插件的service。
       我们现在定义一个插件管理的Service接口。        

None.gif using  System;
None.gif
using  System.Collections.Generic;
None.gif
using  System.Text;
None.gif
None.gif
namespace  PluginFramework
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public interface IPluginService
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        IApplication Application 
dot.gifget;set;}
InBlock.gif        
void AddPlugin(String pluginName, String pluginType, String Assembly, String pluginDescription);
InBlock.gif        
void RemovePlugin(String pluginName);
InBlock.gif        String[] GetAllPluginNames();
InBlock.gif        Boolean Contains(String pluginName);
InBlock.gif        Boolean LoadPlugin(String pluginName);
InBlock.gif        Boolean UnLoadPlugin(String pluginName);
InBlock.gif        IPlugin GetPluginInstance(String pluginName);
InBlock.gif        
void LoadAllPlugin();
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

      PluginService要实现的目标首先是在配置文件中添加/删除要加载的插件以及相关的信息,接下来就是动态的加载插件。我们要定义几个类型:Plugin配置区块类型,Plugin元素类型,plugin元素集合类型,以便我们能够读取插件的信息。
       最后我们实现PluginService:

      
None.gif using  System;
None.gif
using  System.Collections.Generic;
None.gif
using  System.Text;
None.gif
using  System.Xml;
None.gif
using  System.Configuration;
None.gif
using  System.Reflection;
None.gif
using  System.Windows.Forms;
None.gif
using  System.IO;
None.gif
using  System.Collections;
None.gif
None.gif
namespace  PluginFramework
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
public class PluginService : IPluginService
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private IApplication application = null;
InBlock.gif        
private PluginConfigurationSection config = null;
InBlock.gif        
private Dictionary<String, IPlugin> plugins = new Dictionary<string, IPlugin>();
InBlock.gif        
private XmlDocument doc = new XmlDocument();
InBlock.gif
InBlock.gif        
public PluginService()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public PluginService(IApplication application)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.application = application;
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
IPluginService Members#region IPluginService Members
InBlock.gif
InBlock.gif        
public void AddPlugin(string pluginName, string pluginType, string assembly, string pluginDescription)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
InBlock.gif            XmlNode pluginNode 
= doc.SelectSingleNode("/configuration/PluginSection");
InBlock.gif            XmlElement ele 
= doc.CreateElement("add");
InBlock.gif            XmlAttribute attr 
= doc.CreateAttribute("Name");
InBlock.gif            attr.Value 
= pluginName;
InBlock.gif            ele.SetAttributeNode(attr);
InBlock.gif            XmlAttribute attrType 
= doc.CreateAttribute("Type");
InBlock.gif            attrType.Value 
= pluginType;
InBlock.gif            ele.SetAttributeNode(attrType);
InBlock.gif
InBlock.gif            XmlAttribute attrAss 
= doc.CreateAttribute("Assembly");
InBlock.gif            attrAss.Value 
= assembly;
InBlock.gif            ele.SetAttributeNode(attrAss);
InBlock.gif
InBlock.gif            XmlAttribute attrDes 
= doc.CreateAttribute("Description");
InBlock.gif            attrDes.Value 
= pluginDescription;
InBlock.gif            ele.SetAttributeNode(attrDes);
InBlock.gif            pluginNode.AppendChild(ele);
InBlock.gif            doc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
InBlock.gif            ConfigurationManager.RefreshSection(
"PluginSection");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void RemovePlugin(string pluginName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            doc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
InBlock.gif            XmlNode node 
= doc.SelectSingleNode("/configuration/PluginSection");
InBlock.gif            
foreach (XmlNode n in node.ChildNodes)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (n.Attributes != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
if (n.Attributes[0].Value == pluginName)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        node.RemoveChild(n);
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            doc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
InBlock.gif            ConfigurationManager.RefreshSection(
"PluginSection");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public string[] GetAllPluginNames()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            config 
= (PluginConfigurationSection)ConfigurationManager.GetSection("PluginSection");
InBlock.gif            PluginConfigurationElement pe 
= new PluginConfigurationElement();
InBlock.gif            ArrayList ps 
= new ArrayList();
InBlock.gif            
for (Int32 i = 0; i < config.PluginCollection.Count; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                pe 
= config.PluginCollection[i];
InBlock.gif                ps.Add(pe.Name);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
return (String[])ps.ToArray(typeof(String));
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public bool Contains(string pluginName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            config 
= (PluginConfigurationSection)ConfigurationManager.GetSection("PluginSection");
InBlock.gif            PluginConfigurationElement pe 
= new PluginConfigurationElement();
InBlock.gif            List
<String> ps = new List<string>();
InBlock.gif            
for (Int32 i = 0; i < config.PluginCollection.Count; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                pe 
= config.PluginCollection[i];
InBlock.gif                ps.Add(pe.Name);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
return ps.Contains(pluginName);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public bool LoadPlugin(string pluginName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Boolean result 
= false;
InBlock.gif            config 
= (PluginConfigurationSection)ConfigurationManager.GetSection("PluginSection");
InBlock.gif            PluginConfigurationElement pe 
= new PluginConfigurationElement();
InBlock.gif
InBlock.gif            String path 
= Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + "\\Plugin";
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
for (Int32 i = 0; i < config.PluginCollection.Count; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    pe 
= config.PluginCollection[i];
InBlock.gif                    
if (pe.Name == pluginName)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        Assembly assembly 
= Assembly.LoadFile(path + "\\" + pe.Assembly);
InBlock.gif                        Type type 
= assembly.GetType(pe.Type);
InBlock.gif                        IPlugin instance 
= (IPlugin)Activator.CreateInstance(type);
InBlock.gif                        instance.Application 
= application;
InBlock.gif                        instance.Load();
InBlock.gif                        plugins[pluginName] 
= instance;
InBlock.gif                        result 
= true;
InBlock.gif                        
break;
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

InBlock.gif                
if (!result)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    MessageBox.Show(
"Not Found the Plugin");
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch (Exception e)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                MessageBox.Show(e.Message);
InBlock.gif                result 
= false;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
return result;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public bool UnLoadPlugin(string pluginName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Boolean result 
= false;
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                IPlugin plugin 
= GetPluginInstance(pluginName);
InBlock.gif                plugin.UnLoad();
InBlock.gif                result 
= true;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch (Exception e)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                MessageBox.Show(e.Message);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
return result;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void LoadAllPlugin()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            PluginConfigurationElement pe 
= new PluginConfigurationElement();
InBlock.gif            config 
= (PluginConfigurationSection)ConfigurationManager.GetSection("PluginSection");
InBlock.gif            String path 
= Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + "\\Plugin";
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
for (Int32 i = 0; i < config.PluginCollection.Count; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    pe 
= config.PluginCollection[i];
InBlock.gif                    Assembly assembly 
= Assembly.LoadFile(path + "\\" + pe.Assembly);
InBlock.gif                    Type type 
= assembly.GetType(pe.Type);
InBlock.gif                    IPlugin instance 
= (IPlugin)Activator.CreateInstance(type);
InBlock.gif                    instance.Application 
= application;
InBlock.gif                    instance.Load();
InBlock.gif                    plugins[pe.Name] 
= instance;
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch (Exception e)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                MessageBox.Show(e.Message);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public IApplication Application
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
return application;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                application 
= value;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public IPlugin GetPluginInstance(string pluginName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            IPlugin plugin 
= null;
InBlock.gif            
if (plugins.ContainsKey(pluginName))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                plugin 
= plugins[pluginName];
ExpandedSubBlockEnd.gif            }

InBlock.gif            
return plugin;
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
      

    由于代码比较多,我也就不一一列举了,只把比较重要的代码列出来,其余的我会提供源代码的下载。在实现了PluginService以后,我们需要有一个地方能够使用这个Service来管理插件,我的做法是在一个菜单里添加一个项目,当用户点击这个项目的时候弹出插件管理的对话框,用户在这个对话框中选择使用那些插件,当插件被选中的时候,插件会被立即加载进来,并且记录到配置文件里,当用户下次运行应用程序的时候,插件默认会被自动的加载。

       另外从现在开始我们就需要使用配置文件了,所以,我们需要给应用程序添加一个 app.config 文件,文件内容如下:
      
None.gif <? xml version="1.0" encoding="utf-8"  ?>
None.gif
< configuration >
None.gif  
< configSections >
None.gif    
< section
None.gif      
name ="PluginSection"
None.gif      type
="PluginFramework.PluginConfigurationSection, PluginFramework"
None.gif      
/>     
None.gif  
</ configSections >  
None.gif  
< PluginSection >
None.gif    
None.gif  
</ PluginSection >
None.gif
</ configuration >

      样子,总体来说我们就为Plugin的管理提供了一个基本的实现,如果大家还有什么不明白的地方,可以参考我提供的源代码或者通过e-mail和我联系。
      源代码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值