Assembly.GetTypes() - ReflectionTypeLoadException

Ves*_*hky 14 c# reflection plugins assemblies

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

用户提供了插件的路径,我们循环浏览文件夹中的每个文件,看看它(插件)是否支持我们的插件界面.如果是,我们创建一个实例,如果不是,我们移动到下一个文件.

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

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

我们代码的基本版本是;

var pluginAssembly = Assembly.LoadFrom(FileName);    
foreach (var pluginType in pluginAssembly.GetTypes())
{
Run Code Online (Sandbox Code Playgroud)

我们得到一个"ReflectionTypeLoadException"异常.

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

编辑:在遍历LoaderExceptions之后,我们发现有一个文件libPublic.dll会生成System.IO.FileNotFoundException异常.奇怪的是,该文件驻留在应用程序目录中,插件被引用到项目文件中.

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

Dan*_*ant 15

一些东西:

  • 确保插件目录中没有重复的程序集(即您已经从app目录中加载到主应用程序中的程序集.)否则,当您加载插件时,它可能会加载同一程序集的附加副本.这可以带来有趣的例外,例如:

    对象('MyObject'类型)不是'MyObject'类型.

  • 如果在实例化类型时遇到异常,则可能需要处理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;
    }
    
    Run Code Online (Sandbox Code Playgroud)

我意识到告诉CLR有点奇怪,为了解决一个程序集,找到我们用来解析的名字的程序集,但我看到没有它的奇怪事情发生了.例如,我可以从插件程序集中实例化类型,但是如果我尝试使用TypeDescriptor.GetConverter它,它将找不到TypeConverter类,即使它可以Converter在类上看到该属性.


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

  • 你真棒!我遇到了重复装配问题,所以这个答案救了我! (2认同)