I’m trying to debug an assembly import issue on a WPF app that uses MEF to load some plugins and looking for ideas to solve this particular exception:
More than one export was found that matches the constraint:
ContractName MarkPad.Contracts.ISpellingService
RequiredTypeIdentity MarkPad.Contracts.ISpellingService
There is only one assembly that references the plugin of concerndirectly as part of an autofac registration of it (code snippet at the very end).
[ImportingConstructor]
public SpellCheckPlugin(
IPluginSettingsProvider settingsProvider,
ISpellingService spellingService,
ISpellCheckProviderFactory spellCheckProviderFactory)
There is only 1 implementation of ISpellingService
[Export(typeof(ISpellingService))]
public class SpellingService : ISpellingService
This is an open source Code52 project on github.
The plugin import is:
[ImportMany]
IEnumerable<IPlugin> plugins;
What I’ve tried so far:
- This and this blog post make reference to using
[ImportMany(AllowRecomposition = true)]but that also doesn’t seem to help. - Other discussions I found mention setting the ‘Copy Local’ to false, but because it’s actually used in registration code that’s not an option, as it doesn’t end up in the output folder.
Any ideas?
The registration code referencing the plug-in
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);
})
Solution
The problem was a bug where the current assembly via
GetExecutingAssemblywas being used in the PluginManager() as one of the catalog entries in theAggregateCatalogbeing supplied to theCompositionContainer.This bug came about from extracting out the services/plug-ins into their own assemblies, which were originally part of the core MarkPad assembly.
Extra Improvements
As part of this patch there was some extra clean-up that might be useful to support this answer.
Since the SpellCheckPlugin took interfaces, the exports were simply moved to the interfaces themselves not the concrete types.
Adding Export on Interfaces instead
Removing concrete exports