如何在.NET中加载插件?
我想提供一些在软件中创建可动态加载的插件的方法。
典型的方法是使用LoadLibrary WinAPI函数加载dll,然后调用GetProcAddress获取指向该dll中函数的指针。
我的问题是如何在C#/。Net应用程序中动态加载插件?
解决方案
回答
以下代码段(C#)构造了从应用程序路径的类库(* .dll)中找到的Base
派生的任何具体类的实例,并将其存储在列表中。
using System.IO; using System.Reflection; List<Base> objects = new List<Base>(); DirectoryInfo dir = new DirectoryInfo(Application.StartupPath); foreach (FileInfo file in dir.GetFiles("*.dll")) { Assembly assembly = Assembly.LoadFrom(file.FullName); foreach (Type type in assembly.GetTypes()) { if (type.IsSubclassOf(typeof(Base)) && type.IsAbstract == false) { Base b = type.InvokeMember(null, BindingFlags.CreateInstance, null, null, null) as Base; objects.Add(b); } } }
编辑:Matt引用的类在.NET 3.5中可能是更好的选择。
回答
基本上,我们可以通过两种方式做到这一点。
第一种是导入kernel32.dll并使用之前使用的LoadLibrary和GetProcAddress:
[DllImport("kernel32.dll")] internal static extern IntPtr LoadLibrary(String dllname); [DllImport("kernel32.dll")] internal static extern IntPtr GetProcAddress(IntPtr hModule, String procname);
第二种是通过.NET方式进行操作:使用反射。检查System.Reflection命名空间和以下方法:
- Assembly.LoadFile
- Assembly.GetType
- Assembly.GetTypes
- Type.GetMethod
- MethodInfo.Invoke
首先,我们通过程序集的路径加载程序集,然后通过其名称从其获取类型(类),然后再次通过其名称获取该类的方法,最后使用相关参数调用该方法。
回答
从.NET 3.5开始,有一种形式化的嵌入式方法可以从.NET应用程序创建和加载插件。全部都在System.AddIn命名空间中。有关更多信息,我们可以在MSDN上查看此文章:加载项和可扩展性
回答
一个提示是将所有插件等加载到自己的AppDomain中,因为运行的代码可能是恶意的。自己的AppDomain也可以用于"过滤"我们不想加载的程序集和类型。
AppDomain domain = AppDomain.CreateDomain("tempDomain");
并将程序集加载到应用程序域中:
AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyPath); Assembly assembly = domain.Load(assemblyName);
卸载应用程序域:
AppDomain.Unload(domain);
回答
本文较旧,但仍适用于在应用程序中创建可扩展性层:
允许用户使用宏和插件向.NET应用程序添加功能
回答
是的,Matt和System.AddIn的++(有关MSDN的有关System.AddIn的两部分文章,请参见此处和此处)。我们可能希望了解的另一种技术,以了解.NET Framework将来的发展方向是Codeplex上CTP形式的托管扩展框架。