1、接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PlugDemo
{
public interface IPlugToText
{
string ProccessText(string text);
}
}


2、菜单属性Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PlugDemo
{
public class MenuNameAttribute:Attribute
{
private string _name;

public string Name
{
get { return _name; }
set { _name = value; }
}

public MenuNameAttribute(string name)
{
this._name = name;
}

}
}


3、实现接口的实现类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ComPlugDemo
{
[PlugDemo.MenuName("转小写")]
public class PlugToLower : PlugDemo.IPlugToText
{
#region IPlugToText 成员

public string ProccessText(string text)
{
return text.ToLower();
}

#endregion
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ComPlugDemo
{
[PlugDemo.MenuName("转大写")]
public class PlugToUpper:PlugDemo.IPlugToText
{

#region IPlugToText 成员

public string ProccessText(string text)
{
return text.ToUpper();
}

#endregion
}
}


4、反射机制:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
using PlugDemo;


namespace 插件Demo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
AddPlugMenu();
}

void AddPlugMenu()
{
//1、加载正在运行的程序集的物理路径
Assembly ass = this.GetType().Assembly;

string location = ass.Location;

//2、获取 程序集所在文件夹,并转成 插件程序集文件夹的路径
string assDir = Path.GetDirectoryName(location);

string plugDir = assDir + "\\plugs";

//3、扫描 产检文件夹里的 所有程序集文件
string [] dllPaths = Directory.GetFiles(plugDir,"*.dll");

//重点: 获取插件接口 类型对象

//4、遍历程序集文件路径,并加载程序家到内存中
Type iplugType = typeof(IPlugToText);

foreach (string dllPath in dllPaths)
{
//4.1 、根据路径 加载程序集文件 到内存中
Assembly amy = Assembly.LoadFrom(dllPath);

//4.2 、判断程序集中是否有插件类
//4.2.1、获取插件程序集里公有的类
Type[] types = amy.GetExportedTypes();
//4.2.2 循环遍历 插件程序集里的类型 ,判断是否实现记事本插件接口
foreach (Type t in types)
{
//判断 t 是否 实现了接口 IPlugToUpper
if (iplugType.IsAssignableFrom(t))
{
//重要,获取的MenuNameAttribute 特性对象,或将 内部的Name现在到菜单中
object[] atts = t.GetCustomAttributes(typeof(MenuNameAttribute),false);
MenuNameAttribute menuName = atts[0] as MenuNameAttribute;

//重要:根据插件类型,创建 插件类 对象
IPlugToText iplug = Activator.CreateInstance(t) as IPlugToText;

ToolStripMenuItem item = new ToolStripMenuItem(menuName.Name);

plugMenu.DropDownItems.Add(item);

item.Click += new EventHandler(item_Click);

item.Tag = iplug;
}
}
}

}

void item_Click(object sender, EventArgs e)
{
ToolStripMenuItem item = sender as ToolStripMenuItem;

IPlugToText iplug = item.Tag as IPlugToText;
textBox1.Text = iplug.ProccessText(textBox1.Text);
}
}
}