MEF:“无法加载一个或多个请求的类型。检索LoaderExceptions以获取更多信息”

场景:我正在使用Managed Extensibility Framework在运行时根据在单独的dll中定义的接口契约加载插件(导出)。在我的Visual Studio解决方案中,我有3个不同的项目:主机应用程序,类库(定义接口 - “IPlugin”)和另一个实现接口的类库(导出 - “MyPlugin.dll”)。 主机在其自己的根目录中查找导出,因此在测试期间,我构建整个解决方案并将Plugin.dll从Plugin类库bin / release文件夹复制到主机的调试目录,以便主机的DirectoryCatalog可以找到它并且能够将它添加到CompositionContainer。每次重建后都不会自动复制Plugin.dll,所以每次我对合同/实现进行更改时都会手动执行。 但是,有几次我运行主机应用程序而没有先复制(更新的)Plugin.dll,并且它在组合期间抛出异常:
Unable to load one or more of the requested types. Retrieve the LoaderExceptions for more information
这当然是因为它试图导入的Plugin.dll实现了不同版本的IPlugin,其中属性/方法签名不匹配。虽然在受控和受监控的环境中很容易避免这种情况,但通过简单地避免(duh)插件文件夹中过时的IPlugin实现,我不能依赖于可能遇到传统插件的生产环境中的这种假设。 问题是这个异常有效地破坏了整个Compose动作,并且没有导入导出。我宁愿忽略不匹配的IPlugin实现,因此仍会导入实现正确版本的IPlugin的目录中的其他导出。 有没有办法实现这个目标?我在想几种可能的选择: 在调用Compose之前或调用Compose时,要在CompositionContainer上设置一个标志(“忽略失败的导入”) 在
<ImportMany()>
属性上有一个类似的标志 有一种方法可以“挂钩”基于Compose()的迭代过程,并且能够单独处理每个(失败的)导入 使用强名称签名以某种方式仅查找实现当前版本的IPlugin的导入 想法?     
已邀请:
我也遇到过类似的问题。 如果您确定要忽略这些“坏”程序集,那么解决方案是在创建每个程序集目录后立即调用AssemblyCatalog.Parts.ToArray()。这将触发你提到的
ReflectionTypeLoadException
。然后你有机会捕获异常并忽略坏程序集。 为所有“好”程序集创建
AssemblyCatalog
对象后,可以将它们聚合在一个
AggregateCatalog
中并将其传递给
CompositionContainer
构造函数。     
这个问题可能是由几个因素引起的(加载程序集上的任何异常),比如异常说,看看ExceptionLoader(希望)得到一些想法 我发现的另一个问题/解决方案是,当使用DirectoryCatalog时,如果你没有指定第二个参数“searchPattern”,MEF将加载该文件夹中的所有dll(包括第三方),并开始寻找导出类型,也导致此问题,解决方案是在导出类型的所有程序集上都有一个约定名称,并指定在DirectoryCatalog构造函数中,我使用* _Plugin.dll,这样MEF将只加载包含导出类型的程序集 在我的情况下,MEF正在加载一个NHibernate DLL并在LoaderException上抛出一些程序集版本错误(这个错误可能发生在目录中的任何dll),这种方法解决了这个问题     
以下是上述方法的示例:
var di = new DirectoryInfo(Server.MapPath("../../bin/"));

        if (!di.Exists) throw new Exception("Folder not exists: " + di.FullName);

        var dlls = di.GetFileSystemInfos("*.dll");
        AggregateCatalog agc = new AggregateCatalog(); 

        foreach (var fi in dlls)
        {
            try
            {
                var ac = new AssemblyCatalog(Assembly.LoadFile(fi.FullName));
                var parts = ac.Parts.ToArray(); // throws ReflectionTypeLoadException 
                agc.Catalogs.Add(ac);
            }
            catch (ReflectionTypeLoadException ex)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
            }
        }

        CompositionContainer cc = new CompositionContainer(agc);

        _providers = cc.GetExports<IDataExchangeProvider>();
    

要回复问题请先登录注册