No valid exports were found that match the constraint

Jan 17, 2011 at 4:03 PM

I have read other posts with similar problems but haven't managed to figure out what the problem is in this case. I can see from the error that it doesn't like the IUnityContainer but why and how can I fix this? Thank you.

 

Error:

System.ComponentModel.Composition Warning: 1 : The ComposablePartDefinition 'ProjectInfoModule.ProjectInfoModule' has been rejected. 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) No valid exports were found that match the constraint '((exportDefinition.ContractName == "Microsoft.Practices.Unity.IUnityContainer") AndAlso (exportDefinition.Metadata.ContainsKey("ExportTypeIdentity") AndAlso "Microsoft.Practices.Unity.IUnityContainer".Equals(exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))', invalid exports may have been rejected.

Resulting in: Cannot set import 'ProjectInfoModule.ProjectInfoModule..ctor (Parameter="container", ContractName="Microsoft.Practices.Unity.IUnityContainer")' on part 'ProjectInfoModule.ProjectInfoModule'.
Element: ProjectInfoModule.ProjectInfoModule..ctor (Parameter="container", ContractName="Microsoft.Practices.Unity.IUnityContainer") -->  ProjectInfoModule.ProjectInfoModule -->  AssemblyCatalog (Assembly="ProjectInfoModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

 

The Code:

namespace ProjectInfoModule
{
    /// <summary>
    /// A module for listing this high level project details
    /// </summary>
    [ModuleExport(typeof(ProjectInfoModule))]
    public class ProjectInfoModule : IModule
    {
        private readonly ILoggerFacade logger;
        IRegionManager _regionManager;
        IUnityContainer _container;

        /// <summary>
        /// Initializes a new instance of the <see cref="ProjectInfoModule"/> class.
        /// </summary>
        /// <param name="logger">The logger.</param>
        [ImportingConstructor]
        public ProjectInfoModule(IRegionManager regionManager, IUnityContainer container, ILoggerFacade logger)
        {
            if (logger == null)
            {
                throw new ArgumentNullException("logger");
            }

            this.logger = logger;

            _regionManager = regionManager;
            _container = container;
        }

        /// <summary>
        /// Notifies the module that it has be initialized.
        /// </summary>
        public void Initialize()
        {
            this.logger.Log("ProjectInfoModule demonstrates logging during Initialize().", Category.Info, Priority.Medium);
            _container.RegisterType<IProjectInfoDataService, ProjectInfoDataService>();
            _regionManager.RegisterViewWithRegion("Tab1", typeof(ProjectInfoView));
        }
    }
}

And here is the region:

            <sdk:TabControl  Grid.Row="3">
                <sdk:TabItem Header="Project Information">
                    <ItemsControl x:Name="Tab1" Regions:RegionManager.RegionName="Tab1" />
                </sdk:TabItem>

                <sdk:TabItem Header="Icon Request">
                    <ItemsControl x:Name="Tab2" Regions:RegionManager.RegionName="Tab2" />
                </sdk:TabItem>
            </sdk:TabControl>

Jan 17, 2011 at 8:07 PM

Well I backed out everything to do with MEF and I have the modules loading again. Score one for Unity. To be fair, I was converting my code from Unity to MEF 4 months ago when I was pulled off this project. Jumping back in mid changeover was tough to recall where I left off. It would be really nice if MEF could one day add a tool that works like Fusion (used to debug assembly loading issues) which shows you what assembly signature it is looking for. Where it is looking and what if anything it found while searching for the correct assembly. A tool like that would of likely saved me days of trying to guess what it was about the contract that mef didn't like. I still don't know what the problem was and now I am very hesitant to use MEF in the future or recommend it to others despite it's very clear strengths.

Jan 17, 2011 at 10:28 PM

Thanks for the feedback.

We do see your pain. Diagnostics is being improved for the next version. We're aware of shortcomings and we believe we have found decent solutions for them. Hope you give it another try in a near future.

Jan 17, 2011 at 11:33 PM

Thank you. That is great to hear. I'm not giving up on MEF, just feeling a bit frustrated after loosing a week on my current project.  I look forward to updates in the future.

Jan 18, 2011 at 12:01 AM
Edited Jan 18, 2011 at 12:08 AM

Gary, have you tried using MEFX.exe? Or used MEF’s tracing?

 

This post from Daniel is a great reference for diagnosing MEF failures: http://blogs.msdn.com/b/dsplaisted/archive/2010/07/13/how-to-debug-and-diagnose-mef-failures.aspx

 

Glenn

Feb 3, 2011 at 5:50 PM

Heck, you're trying to import IUnityContainer in a MEF scenario?

...No valid exports were found that match the constraint '((exportDefinition.ContractName == "Microsoft.Practices.Unity.IUnityContainer")...

Glenn, put your glasses on.   8^)

 

Feb 4, 2011 at 8:41 PM

As JohnAskew has pointed out above, I guess you've not registered your IUnityContainer instance with the MEF container.

If converting from Unity to MEF, you really need to make sure you remove all IUnityContainer references, and IMHO, you should not ever be injecting an IUnityContainer, what happens if you dicide later on that you want to use a different container (whoops!, that's what's happened here).

You could always create a project specific IoCFacade and abstract away your container altogether.

// This is the offending line
public ProjectInfoModule(IRegionManager regionManager, IUnityContainer container, ILoggerFacade logger) { /* ... */ }

public void Initialize()
{
   /* ... */
   // And this is the cause of the offence
   _container.RegisterType<IProjectInfoDataService, ProjectInfoDataService>();
   /* ... */
}

... and since you're moving to MEF, there's really no need to register your service, do a lazy import in your class that consumes the Service. 

    public class MyServiceConsumer
    {
        [Import]
        public Lazy<IProjectInfoDataService> DataService { get; set; }

        private void MyConsumerMethod()
        {
            DataService.GetData();
        }
    }

provided that

    [Export(typeof(IProjectInfoDataService))]
    public class ProjectInfoDataService : IProjectInfoDataService { }

 

Feb 7, 2011 at 8:19 PM

Ah. good to know. This was my first Prism project and then it was shelved (for 3 months) midway through converting from IUnity to MEF. After 3 months away and a blurry at best distinction of Prism/IUnity/MEF things were not in my favor. Hopefully, this post will help someone that makes a similar mistake.