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));
}
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!
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?
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.