发现多个导出与MEF ImportMany的约束异常匹配

时间:2012-07-14 13:22:02

标签: c# mef

我正在尝试在WPF应用上调试程序集导入问题,该应用程序使用MEF加载一些插件并寻找解决此特定异常的想法:

  

找到多个匹配约束的导出:
  ContractName MarkPad.Contracts.ISpellingService
  RequiredTypeIdentity MarkPad.Contracts.ISpellingService

只有一个程序集引用了这个插件直接作为autofac注册的一部分(最后的代码片段)。

[ImportingConstructor]
public SpellCheckPlugin(
    IPluginSettingsProvider settingsProvider,
    ISpellingService spellingService,
    ISpellCheckProviderFactory spellCheckProviderFactory)

ISpellingService只有一个实现

[Export(typeof(ISpellingService))]
public class SpellingService : ISpellingService

这是一个开源Code52 project on github

插件导入是:

[ImportMany]
IEnumerable<IPlugin> plugins;

到目前为止我尝试了什么:

  1. Thisthis blog帖子引用了[ImportMany(AllowRecomposition = true)],但这似乎也没有帮助。
  2. 我发现其他讨论提到将“复制本地”设置为false,但因为它实际上在注册代码中使用时不是一个选项,因为它不会在输出文件夹中结束。
  3. 有什么想法吗?

    引用插件的注册码

    builder.RegisterType<SpellingService>().As<ISpellingService>()
        .SingleInstance()
        .OnActivating(args =>
    {
        var settingsService = args.Context.Resolve<ISettingsProvider>();
        var settings = settingsService.GetSettings<SpellCheckPlugin.SpellCheckPluginSettings>();
        args.Instance.SetLanguage(settings.Language);
    })
    

1 个答案:

答案 0 :(得分:4)

解决方案

问题是一个错误,其中当前程序集通过GetExecutingAssembly在PluginManager()中用作AggregateCatalog中提供给CompositionContainer的目录条目之一。< / p>

var catalog = new AggregateCatalog();

// This was causing the composition to detect additional imports
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));

这个错误来自于将服务/插件提取到他们自己的程序集中,这些程序集最初是核心MarkPad程序集的一部分。

  

信用转到@shiftkey和此patch

额外改进

作为此补丁的一部分,有一些额外的清理可能对支持这个答案很有帮助。

由于SpellCheckPlugin接受了接口,因此导出只是移动到接口本身而不是具体类型。

[ImportingConstructor]
public SpellCheckPlugin(
    IPluginSettingsProvider settingsProvider,
    ISpellingService spellingService,
    ISpellCheckProviderFactory spellCheckProviderFactory)

在接口上添加导出

[InheritedExport]
public interface ISpellCheckProviderFactory

// and

[InheritedExport]
public interface ISpellingService  

删除具体出口

[Export(typeof(ISpellingService))]
public class SpellingService : ISpellingService

// and

[Export(typeof(ISpellCheckProviderFactory))]
public class SpellCheckProviderFactory : ISpellCheckProviderFactory