这两天一直在研究这个插件功能的实现,总结一些心得吧。
首先是应该定义插件应该实现的接口,接口里面是插件需要实现的功能与提供的内容。我是这么设计的:
首先是建立一个新的类库,用于把我们支持的插件的类型都以接口的形式放进去。比如我现在为我的Service Master设计了以下几个插件类型:外观插件,功能插件,系统信息插件,其他类型插件。目前接口设计如下
然后在原有的软件项目(ServiceMaster)中添加了一个插件检测的类,这个类用于检测已经放到Plugin文件夹下的插件。
下载: PluginCheck.cs
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Reflection;
- using System.IO;
- using System.Collections;
- namespace ServiceMaster
- {
- public static class PluginCheck
- {
- public static IPluginMenu[] getAllPluginsMenu()
- {
- IPluginInfo[] plugins = getAllPluginsInfo();
- List menus = new List();
- foreach (IPluginInfo plugin in plugins)
- {
- if (plugin is IPluginMenu)
- menus.Add((IPluginMenu)plugin);
- }
- return menus.ToArray();
- }
- public static IPluginInfo[] getAllPluginsInfo()
- {
- if (Directory.Exists(Directory.GetCurrentDirectory() + @"\Plugin"))
- {
- string[] files = Directory.GetFiles(Directory.GetCurrentDirectory() + @"\Plugin");
- List dlls = new List();
- foreach(string file in files)
- {
- FileInfo info = new FileInfo(file);
- if (info.Extension == ".dll")
- dlls.Add(getPluginClass(info.Name, "PluginInfo"));
- }
- return dlls.ToArray();
- }
- else
- {
- Directory.CreateDirectory(Directory.GetCurrentDirectory() + @"\Plugin");
- return new IPluginInfo[0];
- }
- }
- public static IPluginInfo getPluginClass(string filename,string className)
- {
- Assembly ass = null;
- try
- {
- ass = Assembly.LoadFrom(@"plugin\" + filename);
- }
- catch (BadImageFormatException)
- {
- return null;
- }
- string nspace=System.IO.Path.GetFileNameWithoutExtension(filename);
- Type search = ass.GetType(nspace + "." + className);
- if (search==null)
- return null;
- Object o = Activator.CreateInstance(search);
- IPluginInfo info = (IPluginInfo)o;
- return info;
- }
- }
- }
然后的工作就是就是编写插件了。
得益于.Net平台的CLR,在VS上写出的所有的类库都是可以用的,不管你是用C++还是C#还是其他
就以C#为例说一下写一个插件的步骤
- 建一个类库
- 在引用里面添加我们写好的PluginSupport.dll
- 然后建一个类,类名一定是PluginInfo.cs。记得一定加上using ServcieMaster
- 然后让这个类实现上面的任意一个或者多个继承于IPluginInfo的接口(也可以只实现IPluginSysInfo,但是那样的话我的ServiceMaster只能认出来是一个插件,但是没有实际功能)
- 完善功能
- 编译,生成DLL
- 把生成的插件放到ServiceMaster的Plugin文件夹下
- 运行ServiceMaster!
这是一个示例的插件
下载: TestPlugin.cs
- using System;
- using System.Collections.Generic;
- using System.Text;
- using ServiceMaster;
- using System.Reflection;
- namespace testPlugin
- {
- public class PluginInfo:IPluginMenu
- {
- #region IPluginInfo 成员
- string IPluginInfo.AutherWebUrl
- {
- get
- {
- return "http://dkmilan.72pines.com";
- }
- }
- string IPluginInfo.Author
- {
- get
- {
- return "DKMILAN";
- }
- }
- string IPluginInfo.Name
- {
- get
- {
- return "TestPlugin";
- }
- }
- string IPluginInfo.Version
- {
- get { return "1.0.0.0"; }
- }
- #endregion
- #region IPluginMenu 成员
- System.Windows.Forms.ToolStripMenuItem IPluginMenu.PluginMenu
- {
- get
- {
- System.Windows.Forms.ToolStripMenuItem MenuOne = new System.Windows.Forms.ToolStripMenuItem();
- System.Windows.Forms.ToolStripMenuItem MenuTwo = new System.Windows.Forms.ToolStripMenuItem();
- System.Windows.Forms.ToolStripMenuItem topMenu = new System.Windows.Forms.ToolStripMenuItem();
- //
- // MenuOne
- //
- MenuOne.Name = "MenuOne";
- MenuOne.Size = new System.Drawing.Size(148, 22);
- MenuOne.Text = "Hello!";
- MenuOne.Click += new System.EventHandler(MenuOne_Click);
- //
- // MenuTwo
- //
- MenuTwo.Name = "MenuTwo";
- MenuTwo.Size = new System.Drawing.Size(148, 22);
- MenuTwo.Text = "Hello 2~";
- MenuTwo.Click += new System.EventHandler(MenuTwo_Click);
- //
- // topMenu
- //
- topMenu.Name = "topMenu";
- topMenu.Size = new System.Drawing.Size(148, 22);
- topMenu.Text = "插件菜单";
- //
- topMenu.DropDownItems.Add(MenuOne);
- topMenu.DropDownItems.Add(MenuTwo);
- return topMenu;
- }
- }
- #endregion
- private void MenuOne_Click(object sender, EventArgs e)
- {
- System.Windows.Forms.MessageBox.Show("Enjoy ServiceMaster!");
- }
- private void MenuTwo_Click(object sender, EventArgs e)
- {
- System.Windows.Forms.MessageBox.Show("My Plugin!");
- }
- }
- }










1 response so far ↓
lily // May 27th 2008 at 11:06 上午
这个代码贴的养眼~
Leave a Comment