如何在.NET中加载插件?

时间:2020-03-05 18:40:16  来源:igfitidea点击:

我想提供一些在软件中创建可动态加载的插件的方法。
典型的方法是使用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形式的托管扩展框架。