尝试使用 MEF 加载插件时出错

Error when try load plugin using MEF

控制台应用程序尝试使用来自特殊 "plugins" 文件夹的 MEF 加载插件。 另一方面,应用程序的二进制文件夹包含 "legacy" 版本的插件 "PluginAdd.dll"。 控制台应用程序失败并出现错误:

Unhandled Exception: System.Reflection.ReflectionTypeLoadException: Unable to lo
ad one or more of the requested types. Retrieve the LoaderExceptions property fo
r more information.
   at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
   at System.Reflection.RuntimeModule.GetTypes()
   at System.Reflection.Assembly.GetTypes()
   at System.ComponentModel.Composition.Hosting.AssemblyCatalog.get_InnerCatalog
()

如何解决仅从专用文件夹(而非二进制文件夹)加载 MEF 插件的问题和请求?

示例已加载到 git(项目 MEF 加载问题):https://github.com/constructor-igor/TechSugar/trunk/MEF/MEF

下一个代码加载的插件:

public class Client
{
    [ImportMany]
    public Lazy<ICommandPlugin, IDictionary<string, object>>[] CommandPlugins { get; set; }

    public void LoadPlugins()
    {
        var aggregateCatalog = new AggregateCatalog();               

        var pluginAssemblyCatalog = new AssemblyCatalog(@"..\..\..\@PluginBinaries\PluginAdd.dll");            
        aggregateCatalog.Catalogs.Add(pluginAssemblyCatalog);

        var container = new CompositionContainer(aggregateCatalog);
        container.ComposeParts(this);
    }
}

应用程序的配置文件包含插件文件夹的路径:

<probing privatePath="..\..\..\@PluginBinaries"/>

UPD1 添加了完整的异常堆栈跟踪

Unhandled Exception: System.Reflection.ReflectionTypeLoadException: Unable to lo
ad one or more of the requested types. Retrieve the LoaderExceptions property fo
r more information.
   at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
   at System.Reflection.RuntimeModule.GetTypes()
   at System.Reflection.Assembly.GetTypes()
   at System.ComponentModel.Composition.Hosting.AssemblyCatalog.get_InnerCatalog
()
   at System.ComponentModel.Composition.Hosting.AssemblyCatalog.GetExports(Impor
tDefinition definition)
   at System.ComponentModel.Composition.Hosting.AggregateCatalog.GetExports(Impo
rtDefinition definition)
   at System.ComponentModel.Composition.Hosting.CatalogExportProvider.InternalGe
tExportsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.CatalogExportProvider.InnerCatal
ogExportProvider.GetExportsCore(ImportDefinition definition, AtomicComposition a
tomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore
(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1
& exports)
   at System.ComponentModel.Composition.Hosting.CatalogExportProvider.GetExports
Core(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore
(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1
& exports)
   at System.ComponentModel.Composition.Hosting.ExportProvider.GetExports(Import
Definition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.AggregateExportProvider.GetExpor
tsCore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore
(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1
& exports)
   at System.ComponentModel.Composition.Hosting.CompositionContainer.GetExportsC
ore(ImportDefinition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ExportProvider.TryGetExportsCore
(ImportDefinition definition, AtomicComposition atomicComposition, IEnumerable`1
& exports)
   at System.ComponentModel.Composition.Hosting.ExportProvider.GetExports(Import
Definition definition, AtomicComposition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ImportEngine.TryGetExports(Expor
tProvider provider, ComposablePart part, ImportDefinition definition, AtomicComp
osition atomicComposition)
   at System.ComponentModel.Composition.Hosting.ImportEngine.TrySatisfyImportSub
set(PartManager partManager, IEnumerable`1 imports, AtomicComposition atomicComp
osition)
   at System.ComponentModel.Composition.Hosting.ImportEngine.TrySatisfyImportsSt
ateMachine(PartManager partManager, ComposablePart part)
   at System.ComponentModel.Composition.Hosting.ImportEngine.TrySatisfyImports(P
artManager partManager, ComposablePart part, Boolean shouldTrackImports)
   at System.ComponentModel.Composition.Hosting.ImportEngine.SatisfyImports(Comp
osablePart part)
   at System.ComponentModel.Composition.Hosting.ComposablePartExportProvider.<>c
__DisplayClass2.<Compose>b__0()
   at System.ComponentModel.Composition.Hosting.CompositionServices.TryInvoke(Ac
tion action)
   at System.ComponentModel.Composition.Hosting.ComposablePartExportProvider.Com
pose(CompositionBatch batch)
   at System.ComponentModel.Composition.Hosting.CompositionContainer.Compose(Com
positionBatch batch)
   at System.ComponentModel.Composition.AttributedModelServices.ComposeParts(Com
positionContainer container, Object[] attributedParts)
   at MEF_loading_issue.Client.LoadPlugins() in d:\My\MyProjects\@TechSugar\Tech
Sugar.Samples\trunk\MEF\MEF\MEF-loading-issue\Program.cs:line 40
   at MEF_loading_issue.Program.Main() in d:\My\MyProjects\@TechSugar\TechSugar.
Samples\trunk\MEF\MEF\MEF-loading-issue\Program.cs:line 19

UPD2 添加了带有异常消息的屏幕

UPD3 CompositionContainer loading wrong directory through DirectoryCatalog 中描述的相同问题,但未找到确切答案

找到解决方法: 而不是

var pluginAssemblyCatalog = new AssemblyCatalog(@"..\..\..\@PluginBinaries\PluginAdd.dll");

可以使用

var pluginAssemblyCatalog = new AssemblyCatalog(Assembly.LoadFrom(@"..\..\..\@PluginBinaries\PluginAdd.dll"));

在这种情况下,MEF 从专用文件加载插件,而不是从 "binary" 文件夹加载。

Load 上下文通常优于 LoadFrom 上下文。因此,当 MEF 从文件加载程序集时,它将首先获取程序集名称,然后尝试对其执行 Assembly.Load 以将其加载到 Load 上下文中。仅当此操作失败时,它才会在 LoadFrom 上下文中加载程序集。

所以加载旧版插件的原因是因为这是 MEF 更喜欢的加载上下文中可用的版本。

最好从应用程序的二进制文件夹中删除插件的旧版本。我不知道它为什么在那里,所以我不知道这是否适合你。