该例通过反射加载plugins文件夹下实现了IEditor接口的dll插件程序集。其中IEditor接口单独写在一个类库中。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//1、检查plugins目录下是否有dll文件
//1.1获取当前执行的exe文件的绝对路径
string exePath = Assembly.GetExecutingAssembly().Location;
//获取插件的目录路径
string pluginsPath = Path.Combine(Path.GetDirectoryName(exePath),"plugins");
//2、如果有dll文件,则循环遍历,将每个dll文件都通过Assembly.LoadFile()加载起来,然后获取dll程序集中的类型。
//2.1搜索pluginsPath目录下是否有对应的dll文件
//返回值是一个string数组,里面存储这每个dll文件的完整路径
string[] dlls = Directory.GetFiles(pluginsPath,"*.dll");//注意是“dll”程序集
//循环遍历把每个插件都加载起来
foreach (string itemin dlls)
{
//获取当前插件(程序集),这里的每个item就是一个dll的完整路径
Assembly asem = Assembly.LoadFile(item);
//遍历asem这个插件(程序集)中的每个类型,找到那些public类型,并且是实现了IEditor接口的那些类
//获取所有public类型
Type[] types = asem.GetExportedTypes();
//获得接口的Type
Type typIEditor = typeof(IEditor);
//遍历每个类型看看这个类型是否实现了IEditor接口的类型
foreach (Type typeClassin types)
{
//2、判断这个类型是否实现了IEditor接口而且可以被实例化,否则不能用
if (typIEditor.IsAssignableFrom(typeClass)&&!typeClass.IsAbstract)
{
//创建一个typeClass类型的对象
IEditor editor = (IEditor)Activator.CreateInstance(typeClass);
//在菜单栏中将该插件的名字加进去
ToolStripItem tsiMenu = this.格式ToolStripMenuItem.DropDownItems.Add(editor.PluginName);
tsiMenu.Tag = editor;//将插件放到Tag中
//为tsiMenu注册单击事件
tsiMenu.Click += new EventHandler(tsiMenu_Click);
}
}
}
}
//新增插件菜单项的单击事件
void tsiMenu_Click(object sender, EventArgs e)
{
//sender就是当前单击的菜单项
ToolStripItem tsi = (ToolStripItem)sender;
IEditor editor = (IEditor)tsi.Tag;
editor.StartProgram(textBox1);
}
}
public interface IEditor
{
///<summary>
///是一个只读属性,里面存储的是插件名称
///</summary>
string PluginName
{
get;
}
//启动插件
void StartProgram(TextBox txtBox);
}