我想提供一些在我的软件中创建动态可加载插件的方法。执行此操作的典型方法是使用 加载库 WinAPI函数加载dll并调用 获取进程地址 获取指向该 dll 内函数的指针。

我的问题是如何在 C#/.Net 应用程序中动态加载插件?

有帮助吗?

解决方案

以下代码片段 (C#) 构造派生自的任何具体类的实例 Base 在应用程序路径中的类库 (*.dll) 中找到并将它们存储在列表中。

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);
        }
    }
}

编辑: 所引用的类 马特 可能是 .NET 3.5 中更好的选择。

其他提示

从 .NET 3.5 开始,有一种正式的内置方法可以从 .NET 应用程序创建和加载插件。这一切都在 系统插件 命名空间。欲了解更多信息,您可以查看 MSDN 上的这篇文章: 插件和可扩展性

动态加载插件

有关如何动态加载 .NET 程序集的信息,请参阅 这个问题 (和 我的答案)。这是一些用于加载创建的代码 AppDomain 并将程序集加载到其中。

var domain = AppDomain.CreateDomain("NewDomainName");
var pathToDll = @"C:\myDll.dll"; 
var t = typeof(TypeIWantToLoad);
var runnable = domain.CreateInstanceFromAndUnwrap(pathToDll, t.FullName) 
    as IRunnable;
if (runnable == null) throw new Exception("broke");
runnable.Run();

卸载插件

插件框架的一个典型要求是卸载插件。卸载动态加载的程序集(例如插件和加载项)您必须卸载包含的 AppDomain. 。欲了解更多信息,请参阅 MSDN 上有关卸载 AppDomain 的文章.

使用WCF

有一个 堆栈溢出问题及解答 描述如何使用 Windows 通信框架 (WCF) 创建插件框架。

现有插件框架

我知道两个插件框架:

有些人谈论 托管可扩展性框架 (MEF) 作为插件或附加框架,但它不是。欲了解更多信息,请参阅 这个 StackOverflow.com 问题这个 StackOverflow.com 问题.

一个技巧是将所有插件等加载到自己的 AppDomain 中,因为运行的代码可能是潜在的恶意代码。自己的 AppDomain 还可以用于“过滤”您不想加载的程序集和类型。

AppDomain domain = AppDomain.CreateDomain("tempDomain");

并将程序集加载到应用程序域中:

AssemblyName assemblyName = AssemblyName.GetAssemblyName(assemblyPath);
Assembly assembly = domain.Load(assemblyName);

要卸载应用程序域:

AppDomain.Unload(domain);

是的,++ 到 Matt 和 System.AddIn(有关 System.AddIn 的两部分 MSDN 杂志文章可用 这里这里)。您可能想要了解 .NET Framework 未来发展方向的另一项技术是 托管可扩展性框架 目前在 Codeplex 上以 CTP 形式提供。

基本上你可以通过两种方式做到这一点。

第一种是导入 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 命名空间和以下方法:

首先,通过程序集的路径加载程序集,然后通过名称从中获取类型(类),然后再次通过名称获取类的方法,最后使用相关参数调用该方法。

该文章有点旧,但仍然适用于在应用程序中创建可扩展层:

让用户使用宏和插件向您的 .NET 应用程序添加功能

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top