.NET: 如何通过AppDomain动态加载插件程序
这是今天课堂上的一个小例子程序
1. 接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Interfaces { public interface IPlugin { void Run(); } }
2. 插件
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace PluginLib { [Serializable] public class Plugin:Interfaces.IPlugin { public void Run() { Console.WriteLine("插件在运行"); } } }
3. 主程序
AppDomain plugindomain = AppDomain.CreateDomain("PluginDomain");
#region 使用接口的方式来动态执行方法 Interfaces.IPlugin plugin = (Interfaces.IPlugin)plugindomain.CreateInstanceFromAndUnwrap("PluginLib.dll", "PluginLib.Plugin"); plugin.Run(); Console.WriteLine("在插件程序域中加载的程序集"); foreach (var item in plugindomain.GetAssemblies()) { Console.WriteLine(item.FullName); } #endregion
结果如下
注意:这种方式加载的插件,里面的类型必须声明可序列化([Serializable] ),否则就会出现下面的错误
但是,如果插件真的没有声明可序列化,是不是就没有办法呢?也不是这么说
4. 在主程序中添加一个TypeLoader
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.IO; namespace _08_AppDomain_ServiceSample { [Serializable] public class TypeLoader { public Assembly LoadAssembly(string path) { return Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, path)); } } }
5. 修改代码,利用TypeLoader作为中间人,去动态加载那些插件程序集
#region 使用加载代理的方式 TypeLoader loader = (TypeLoader)plugindomain.CreateInstanceFromAndUnwrap("08_AppDomain_ServiceSample.exe", typeof(TypeLoader).FullName); Interfaces.IPlugin plugin = (Interfaces.IPlugin)loader.LoadAssembly("PluginLib.dll").CreateInstance("PluginLib.Plugin"); plugin.Run(); Console.WriteLine("在插件程序域中加载的程序集"); foreach (var item in plugindomain.GetAssemblies()) { Console.WriteLine(item.FullName); } AppDomain.Unload(plugindomain); #endregion