我们为应用程序实现了一个插件框架,并使用Assembly.Loadfrom加载插件程序集。然后,我们使用GetTypes()并进一步检查每个插件文件的类型以获取受支持的接口(interface)。

用户提供了插件的路径,我们循环浏览文件夹中的每个文件,以查看其(插件)是否支持我们的插件界面。如果是这样,我们将创建一个实例,否则,我们将移至下一个文件。

我们从一个代码库(appA_1和appA_2)构建两个版本的软件。

当插件是由与插件文件同时构建的应用程序加载时,加载插件的效果很好。但是,如果我们构建appA_2并指向appA_1的插件文件夹,则在调用GetTypes()时会出现异常。

我们代码的基本版本是:

var pluginAssembly = Assembly.LoadFrom(FileName);
foreach (var pluginType in pluginAssembly.GetTypes())
{

我们得到一个“ReflectionTypeLoadException”异常。

这很令人担忧,因为我们希望我们的应用程序能够加载任何人构建的任何插件的类型。我们缺少什么吗?

编辑:
遍历LoaderExceptions之后,我们发现只有一个文件libPublic.dll生成System.IO.FileNotFoundException异常。奇怪的是,该文件位于应用程序目录中,并且插件引用了项目文件。

编辑2:
在异常日志中,我们发现以下内容
“比较程序集名称导致不匹配:修订号”

最佳答案

一些东西:

  • 确保插件目录中没有重复的程序集(即,已经从应用程序目录中的主应用程序中加载的程序集。)否则,当您加载插件时,它可能会加载相同的附加副本部件。这可能会导致有趣的异常,例如:

  • 如果在实例化类型时遇到异常,则可能需要处理AppDomain.AssemblyResolve:
    private void App_Startup(object sender, StartupEventArgs e)
    {
        // Since we'll be dynamically loading assemblies at runtime,
        // we need to add an appropriate resolution path
        // Otherwise weird things like failing to instantiate TypeConverters will happen
        AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
    }
    
    private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        var domain = (AppDomain) sender;
    
        foreach (var assembly in domain.GetAssemblies())
        {
            if (assembly.FullName == args.Name)
            {
                return assembly;
            }
        }
    
        return null;
    }
    

  • 我知道必须告诉CLR为了解析程序集,找到具有我们要用来解析的名称的程序集,这有点奇怪,但是我看到没有它会发生奇怪的事情。例如,我可以从插件程序集中实例化类型,但是如果尝试使用TypeDescriptor.GetConverter,即使找不到类的TypeConverter属性,它也找不到该类的Converter

    查看您的编辑,这可能不是导致当前异常的原因,尽管您稍后在使用插件时可能会遇到这些问题。

    10-07 14:23