Search code examples
wpftelerikprismmef

RegisterMapping complains about "More than one export was found"?


I'm using Prism v4 and MEF together with Telerik RadDocking. In order to use Prism and MEF together with these docking panes, a custom adapter is needed. I have a working adapter which is exported as follows:

[Export]
public class RadPaneGroupRegionAdapter : RegionAdapterBase<RadPaneGroup>
{
    [ImportingConstructor]
    public RadPaneGroupRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
        : base(regionBehaviorFactory)
    {
    }
    ...
}

I configure the aggregate catalogs in the bootstrapper as follows:

protected override void ConfigureAggregateCatalog()
{
    this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));
    this.AggregateCatalog.Catalogs.Add(new DirectoryCatalog("Modules"));
    this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(ViewModelLocator).Assembly));
    this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(MyContractClass).Assembly));
}

Prism complains about multiple exports?

The problem is that when I try to add this adapter to the Prism adapter mappings, I get an ImportCardinalityMismatchException telling me that "More than one export was found that matches the constraint: xxx.Adapters.RadPaneGroupRegionAdapter"

protected override RegionAdapterMappings ConfigureRegionAdapterMappings()
{
    RegionAdapterMappings mappings = base.ConfigureRegionAdapterMappings();
    mappings.RegisterMapping(typeof(RadPaneGroup),
        this.Container.GetExportedValue<Adapters.RadPaneGroupRegionAdapter>());

    return mappings;
}

I cannot understand why this happens. The adapter class is in the same assembly as the bootstrapper, so I would expect there to be only one matching export.

Please help!

UPDATE:

If I comment out this line, the exception is never thrown:

this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(MyContractClass).Assembly));

Maybe the problem is that MyContractClass is dependent on the same Telerik controls? If that is the case, how would I solve this ambiguity?


Solution

  • The problem here is that there are more than one candidates for the import and MEF cannot decide which one to use. There are two ways of dealing with such a problem:

    One is to update your constructor to take a sequence of IRegionBehaviorFactory and add the ImportManyAttribute. Of course you will have to decide which factory to keep.

    [ImportingConstructor]
            public RadPaneGroupRegionAdapter([ImportMany]IEnumerable<IRegionBehaviorFactory> regionBehaviorFactory)
                : base(regionBehaviorFactory)
            {
                //Decide which factory to keep.
            }
    

    The other would be to use a FilteredCatalog and ... filter the parts. You can read this article on filtering catalogs.

    Both approaches will be more efficient if you add export metadata.