如何在.NET中加载插件?
我想提供一些在我的软件中创建动态可加载插件的方法。 典型的方法是使用 LoadLibrary WinAPI函数加载 dll 并调用 GetProcAddress 获取指向该 dll 内函数的指针。
我的问题是如何在 C#/.Net 应用程序中动态加载插件?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
动态加载插件
有关如何动态加载 .NET 程序集的信息,请参阅 这个问题(以及我的答案)。 下面是一些用于加载创建
AppDomain
并将程序集加载到其中的代码。卸载插件
插件框架的一个典型需求是卸载插件。 要卸载动态加载的程序集(例如插件和加载项),您必须卸载包含的
AppDomain
。 有关详细信息,请参阅MSDN 上这篇有关卸载 AppDomain 的文章。使用 WCF
有一个堆栈溢出问题和答案,描述了如何使用 Windows 通信框架 (WCF) 创建插件框架。
现有插件框架
我知道两个插件框架:
System.AddIn
命名空间,如Matt 在他的回答中提到的。有些人将托管扩展性框架 (MEF) 视为插件-in 或附加框架,但它不是。 有关详细信息,请参阅此 StackOverflow.com 问题和此 StackOverflow.com 问题。
Dynamically Loading Plug-ins
For information on how to dynamically load .NET assemblies see this question (and my answer). Here is some code for loading creating an
AppDomain
and loading an assembly into it.Unloading Plug-ins
A typical requirement of a plugin framework is to unload the plugins. To unload dynamically loaded assemblies (e.g. plug-ins and add-ins) you have to unload the containing
AppDomain
. For more information see this article on MSDN on Unloading AppDomains.Using WCF
There is a stack overflow question and answer that describe how to use the Windows Communication Framework (WCF) to create a plug-in framework.
Existing Plug-in Frameworks
I know of two plug-in frameworks:
System.AddIn
namespace as mentioned by Matt in his answer.Some people talk about the Managed Extensibility Framework (MEF) as a plug-in or add-in framework, which it isn't. For more information see this StackOverflow.com question and this StackOverflow.com question.
一个技巧是将所有插件等加载到自己的 AppDomain 中,因为运行的代码可能是恶意的。 自己的 AppDomain 还可以用于“过滤”您不想加载的程序集和类型。
并将程序集加载到应用程序域中:
卸载应用程序域:
One tip is to load all plugins and such into an own AppDomain, since the code running can be potentially malicious. An own AppDomain can also be used to "filter" assemblies and types that you don't want to load.
And to load an assembly into the application domain:
To unload the application domain:
以下代码片段 (C#) 构造从应用程序路径中的类库 (*.dll) 中找到的
Base
派生的任何具体类的实例,并将它们存储在列表中。编辑: Matt 可能是 .NET 3.5 中更好的选择。
The following code snippet (C#) constructs an instance of any concrete classes derived from
Base
found in class libraries (*.dll) in the application path and stores them in a list.Edit: The classes referred to by Matt are probably a better option in .NET 3.5.
从 .NET 3.5 开始,有一种正式的内置方法可以从 .NET 应用程序创建和加载插件。 它全部位于 System.AddIn 命名空间中。 有关详细信息,您可以查看 MSDN 上的这篇文章:加载项和扩展性
As of .NET 3.5 there's a formalized, baked-in way to create and load plugins from a .NET application. It's all in the System.AddIn namespace. For more information you can check out this article on MSDN: Add-ins and Extensibility
这是我的实现,灵感来自 此代码避免迭代所有程序集和所有类型(或至少使用 linQ 进行过滤)。 我只是加载库并尝试加载实现公共共享接口的类。 简单而快速:)
只需在单独的库中声明一个接口并在您的系统和插件中引用它:
在您的插件库中,声明一个实现 IYourInterface 的类
在您的系统中,声明此方法
并像这样调用它:
This is my implementation, Inspired in this code avoiding to iterate over all assemblies and all types (or at least filtering with linQ). I just load the library and try to load the class which implemets a common shared interface. Simple and fast :)
Just declare an interface in a separated library and reference it in both, your system and your plugin:
In your plugin library, declare a class which implements IYourInterface
In your system, declare this method
And call it like this way:
该文章有点旧,但仍然适用于在应用程序中创建可扩展性层:
让用户通过宏和插件向您的 .NET 应用程序添加功能
The article is a bit older, but still applicable for creating an extensibility layer within your application:
Let Users Add Functionality to Your .NET Applications with Macros and Plug-Ins
基本上你可以通过两种方式做到这一点。
第一种方法是导入 kernel32.dll 并像以前一样使用 LoadLibrary 和 GetProcAddress:
第二种方法是以 .NET 方式执行此操作:通过使用反射。 检查 System.Reflection 命名空间和以下方法:
首先通过程序集的路径加载程序集,然后通过名称从中获取类型(类),然后获取方法再次按类的名称调用该类,最后使用相关参数调用该方法。
Basically you can do it in two ways.
The first is to import kernel32.dll and use LoadLibrary and GetProcAddress as you used it before:
The second is to do it in the .NET-way: by using reflection. Check System.Reflection namespace and the following methods:
First you load the assembly by it's path, then get the type (class) from it by it's name, then get the method of the class by it's name again and finally call the method with the relevant parameters.
是的,++ 到 Matt 和 System.AddIn(有关 System.AddIn 的两部分 MSDN 杂志文章可参考 此处和此处) 。 您可能想要了解 .NET Framework 未来发展方向的另一项技术是 托管可扩展性框架目前以 CTP 形式在 Codeplex 上提供。
Yes, ++ to Matt and System.AddIn (a two-part MSDN magazine article about System.AddIn are available here and here). Another technology you might want to look at to get an idea where the .NET Framework might be going in the future is the Managed Extensibility Framework currently available in CTP form on Codeplex.