Problem in getting MEF with Unity and constructor-parameter-injection running

May 27, 2010 at 11:57 AM

Hi folks,

I am using MEFContrib alongside with MEF (for sure ;-) ) and Unity v2 - especially the integration layer to get both worlds working together.

As I am using the app.config to configure Unity the bootstrapping process looks like this:

 

// Bootstrapping Unity
IUnityContainer container = new UnityContainer();

UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(container, "SystemManagamentService");

// Bootstrapping MEF
DirectoryCatalog extensionCatalog = new DirectoryCatalog(".");
AggregateCatalog baseCatalog = new AggregateCatalog(extensionCatalog);

// Integrating Unity with MEF
container.RegisterCatalog(baseCatalog);

CommonServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));

 

There is a ConverterManager (Registered via Unity) which has Converters which are loaded by MEF:

 

    public sealed class ConverterManager
        : IConverterManager
    {
        #region Public Properties

        [ImportMany(typeof(IConverter))]
        public Lazy<IConverter, Dictionary<string, object>>[] Converter
        {
            get; set;
        }

        #endregion Public Properties

        #region Public Functions

        public IEnumerable<IConverter> GetConverter(string messageType)
        {
            return from converter 
                     in this.Converter
                  where converter.Metadata["ContentType"].ToString() == messageType
                 select converter.Value;
        }

        #endregion Public Functions
    }

 

Each Converter is looking something like this:

 

    [Export(typeof(IConverter))]
    [ExportMetadata("ContentType", "WWKS-XML")]
    public sealed class WWKSXMLConverter 
        : IConverter
    {
        #region Private Member

        private readonly IDataService _DataService;

        #endregion Private Member

        #region Private Properties

        private IDataService DataService
        {
            get
            {
                return this._DataService;
            }
        }

        #endregion Private Properties

        #region Constructor

        [ImportingConstructor]
        public WWKSXMLConverter(IDataService dataService)
        {
            if (null == dataService)
            {
                throw new ArgumentNullException("dataService");
            }

            this._DataService = dataService;
        }

        #endregion Constructor

The Problem is: I am getting an CompositionException saying that the IDataService Type isn't registered. But from Unity / CSL I can resolve the IDataService (configured as a Singleton).

Any help would be appreciated - if further infos are needed just give a hint ;-)

Best regards,

m.

 

 

 

Coordinator
May 27, 2010 at 12:07 PM

Hello,

I assume you cannot resolve types registered in the app.config via MEF ? If so, try placing

TypeRegistrationTrackerExtension.RegisterIfMissing(container);

just after you create UnityContainer. Did it work ?

 

Regards,

Piotr

May 27, 2010 at 1:15 PM

Hi Piotr,

works perfectly - thanks for the quick reply  ^o^

m.

Coordinator
May 27, 2010 at 1:16 PM
Piotr is da bomb :)

On Thu, May 27, 2010 at 3:15 PM, kimpenhaus <notifications@codeplex.com> wrote:

From: kimpenhaus

Hi Piotr,

works perfectly - thanks for the quick reply  ^o^

m.

Read the full discussion online.

To add a post to this discussion, reply to this email (MEFContrib@discussions.codeplex.com)

To start a new discussion for this project, email MEFContrib@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com


May 27, 2010 at 1:23 PM

I remembered the RegisterIfMissing call that I saw in reflector. Just double checked it and it turns out that it is an problem of order in that things are done.

I managed to get it working without the extra call be changing the bootstrapping order to:

            // Bootstrapping Unity
            IUnityContainer container = new UnityContainer();

            // Bootstrapping MEF
            DirectoryCatalog extensionCatalog = new DirectoryCatalog(".");
            AggregateCatalog baseCatalog = new AggregateCatalog(extensionCatalog);

            // Integrating Unity with MEF
            container.RegisterCatalog(baseCatalog);

            UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            section.Configure(container, "SystemManagamentService");

That is working as supected (just as info).

Thanks

Coordinator
May 27, 2010 at 1:35 PM

Yeah, it must have worked =)

The reason of your "problem" is that when you were configuring the Unity via section.Configure, the types get registered in the Unity, but the MEF couldn't track them because it is initialized during the first call to RegisterCatalog.

 

Regards,

Piotr