论坛里有许多插件开发的文章,本文就不长篇大论了,说一下我的简单思路:
1、建一个IPlugin接口,每个插件都要继承这个接口。
2、建一个插件管理类,利用Unity来管理各个插件。
1 using System.Reflection; 2 using Microsoft.Practices.Unity; 3 public interface IPlugin 4 { 5 void LoadPlugin(); 6 string PluginName { get; } 7 } 8 public class PlugInManage 9 { 10 /// <summary> 11 /// 从dll、exe文件中获取继承IPluin接口的所有类的类型信息 12 /// </summary> 13 /// <param name="path">文件路径</param> 14 /// <returns>类型信息(插件名称,(插件类名称,插件所在程序集名称))</returns> 15 public static Dictionary<string, string> Load(string path) 16 { 17 if (!System.IO.Directory.Exists(path)) 18 { 19 throw new System.IO.DirectoryNotFoundException(); 20 } 21 22 Dictionary<string, string> pluins = new Dictionary<string,string>(); 23 var files = System.IO.Directory.GetFiles(path); 24 foreach (var file in files) 25 { 26 if (file.ToLower().EndsWith(".exe") || file.ToLower().EndsWith(".dll")) 27 { 28 var assembly = Assembly.LoadFrom(file); 29 var types = assembly.GetTypes(); 30 foreach (var type in types) 31 { 32 33 if (type.GetInterfaces().Count(c =>c == typeof(IPlugin)) > 0) 34 { 35 36 IPlugin instance = assembly.CreateInstance(type.FullName) as IPlugin; 37 if (instance != null) 38 { 39 _container.RegisterType(typeof(IPlugin), type, type.FullName, new ExternallyControlledLifetimeManager()); 40 41 var name = string.IsNullOrEmpty(instance.PluginName) ? 42 type.FullName : instance.PluginName; 43 name = pluins.ContainsKey(name)?name+"_1":name; 44 pluins.Add(name, type.FullName); 45 } 46 47 } 48 } 49 } 50 } 51 return pluins; 52 } 53 54 static IUnityContainer _container = new UnityContainer(); 55 public static IPlugin Resolve(string name) 56 { 57 GC.Collect(); 58 return _container.Resolve<IPlugin>(name); 59 } 60 61 }
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); } } }
1 using XZL.Plugin; 2 public partial class Form1 : Form,IPlugin 3 { 4 public Form1() 5 { 6 InitializeComponent(); 7 } 8 9 public void LoadPlugIn() 10 { 11 this.Show(); 12 } 13 14 15 string IPlugin.PluginName 16 { 17 get { return this.Text; } 18 } 19 }