0
votes

I've got a project where contains two modules, one infrastructure (Common library) and the Shell.

enter image description here

Note that Common has a FooService, this one has an ExportAttribute

[Export]
public class FooService
{
}

And this one should be used by Module1 and Module2, But it throws me errors if I have the ImportAttribute. Please note the comment.

[ModuleExport("Module1.ModuleInit", typeof(Module1.ModuleInit))]
public class ModuleInit : IModule
{
    private readonly IRegionManager _regionManager;
    public IServiceLocator _serviceLocator;

    // [Import(AllowRecomposition=true)]
    public FooService _service;

    [ImportingConstructor]
    public ModuleInit(IRegionManager regionManager, IServiceLocator serviceLocator)
    {
        _regionManager = regionManager;
        _serviceLocator = serviceLocator;
    }

    public void Initialize() { }
}

This code is the same for Module2.

An exception occurred while initializing module 'Module2.ModuleInit'. - The exception message was: The composition remains unchanged. The changes were rejected because of the following error(s): The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.

1) More than one export was found that matches the constraint '((exportDefinition.ContractName == "Common.FooService") AndAlso (exportDefinition.Metadata.ContainsKey("ExportTypeIdentity") AndAlso "Common.FooService".Equals(exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))'.

Resulting in: Cannot set import 'Module1.ModuleInit._service (ContractName="Common.FooService")' on part 'Module1.ModuleInit'. Element: Module1.ModuleInit._service (ContractName="Common.FooService") --> Module1.ModuleInit --> AssemblyCatalog (Assembly="Module1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

Why am I receiving this exception? I'm just exporting one object. I'd like to know what is happening and how to fix it.

Please feel free to download it, it's very small the project. Download the compact project

2
More than one export was found that matches the constraint...Robert Harvey
I know, but I don't get why MEF exported two ´FooServices´. I mean, the idea is ´FooService´ should be a same instance for all the modulesDarf Zon

2 Answers

0
votes

This should really just be a comment, but I don't have enough rep to do that yet. Anyway, it looks to me like a scoping issue. I believe MEF v1 should automatically treat exports as singletons, but I think it's been reversed in v2 - not sure which version you're using. I ran into an issue recently using Microsoft.Composition (MEF for MVC) and solved it by using HTTP request level scoping to get a single instance for the life of the entire request.

[System.Composition.Export(typeof(ICustomDbContext))]
[System.Composition.Shared(Boundaries.HttpRequest)]
public class CustomDbContext : ICustomDbContext { ... }
0
votes

Solution: You go through each project except the Shell Project, and look at the references; do the following:

  • Just delete the unityextension reference, since you are using MEF
  • Set "Common" reference property "Copy local" to False
  • Set "Microsoft.Practices.Prism" reference property "Copy local" to False
  • Set "Microsoft.Practices.Prism.MefExtensions" reference property "Copy local" to False
  • Set "Microsoft.Practices.Prism.ServiceLocation" reference property "Copy local" to False
  • Set "System.ComponentModel.Composition" reference property "Copy local" to False

Go to the Bootstrapper class, add this:

protected override void ConfigureAggregateCatalog()
        {
            base.ConfigureAggregateCatalog();

            // Add this assembly to the catalog.
            this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));

            // Add the FooService assembly
            this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(FooService).Assembly));
        }

Then uncomment the [Import(AllowRecomposition)] and FooService in your modules.

Before you run your project, you need to go to the Visual Studio menu select Build -> Clean Project. This will delete all the dll files where they previously were copy local true.