作者简单介绍自己的思路:
1、建一个IPlugin接口,每个插件都要继承这个接口。
2、建一个插件管理类,利用Unity来管理各个插件。
代码如下:
using System.Reflection;
using Microsoft.Practices.Unity;
public interface IPlugin
{
void LoadPlugin();
string PluginName { get; }
}
public class PlugInManage
{
/// <summary>
/// 从dll、exe文件中获取继承IPluin接口的所有类的类型信息
/// </summary>
/// <param name="path">文件路径</param>
/// <returns>类型信息(插件名称,(插件类名称,插件所在程序集名称))</returns>
public static Dictionary<string, string> Load(string path)
{
if (!System.IO.Directory.Exists(path))
{
throw new System.IO.DirectoryNotFoundException();
}
Dictionary<string, string> pluins = new Dictionary<string,string>();
var files = System.IO.Directory.GetFiles(path);
foreach (var file in files)
{
if (file.ToLower().EndsWith(".exe") || file.ToLower().EndsWith(".dll"))
{
var assembly = Assembly.LoadFrom(file);
var types = assembly.GetTypes();
foreach (var type in types)
{
if (type.GetInterfaces().Count(c =>c == typeof(IPlugin)) > 0)
{
IPlugin instance = assembly.CreateInstance(type.FullName) as IPlugin;
if (instance != null)
{
_container.RegisterType(typeof(IPlugin), type, type.FullName, new ExternallyControlledLifetimeManager());
var name = string.IsNullOrEmpty(instance.PluginName) ?
type.FullName : instance.PluginName;
name = pluins.ContainsKey(name)?name+"_1":name;
pluins.Add(name, type.FullName);
}
}
}
}
}
return pluins;
}
static IUnityContainer _container = new UnityContainer();
public static IPlugin Resolve(string name)
{
GC.Collect();
return _container.Resolve<IPlugin>(name);
}
}
3、注意容器内注册的类型应为ExternallyControlledLifetimeManager类型的生命周期,外 部控制生命周期管理器,这个生命周期管理允许你使用RegisterType和RegisterInstance来注册对象之间的关系,但是其只会对对象 保留一个弱引用,其生命周期交由外部控制,也就是意味着你可以将这个对象缓存或者销毁而不用在意UnityContainer,而当其他地方没有强引用这 个对象时,其会被GC给销毁掉。在默认情况下,使用这个生命周期管理器,每次调用Resolve都会返回同一对象(单件实例),如果被GC回收后再次调用 Resolve方法将会重新创建新的对象。
测试如下:
using XZL.Plugin;
public partial class Form1 : Form
{
Dictionary<string, string> _plugins;
public Form1()
{
InitializeComponent();
this.Load += new EventHandler(Form1_Load);
this.button1.Click += new EventHandler(button1_Click);
}
void button1_Click(object sender, EventArgs e)
{
var p = PlugInManage.Resolve(_plugins[listBox1.SelectedItem.ToString()]);
p.LoadPlugin();
//GC.Collect();
}
void Form1_Load(object sender, EventArgs e)
{
_plugins = PlugInManage.Load(System.IO.Path.GetDirectoryName(Application.ExecutablePath)
+ "\\" + "plugins");
foreach (var item in _plugins)
{
listBox1.Items.Add(item.Key);
}
}
}
using XZL.Plugin;
public partial class Form1 : Form,IPlugin
{
public Form1()
{
InitializeComponent();
}
public void LoadPlugIn()
{
this.Show();
}
string IPlugin.PluginName
{
get { return this.Text; }
}
}