MEF Exported class with Unity dependency not composed

Jul 10, 2012 at 7:11 AM

Hi all,

I am quite new to this so I may be doing something real dumb but here goes.

Have been using a MEF directory cataglog and a CompositionContainer to populate a list of objects and runtimes (based on the components in my directory.

It goes something like this

 

[ImportMany(typeof(IPlugin))]
public List<IPlugin> MyPlugins { get; set; }

var catalog = new DirectoryCatalog("PluginFolder");
var container = new CompositionContainer(catalog);
container.ComposeParts(this);

 

It was working perfectly fine and populating my MyPlugins property with my 2 plugins.

I have since added unity into my solution and have add a dependency to one of my plugin classes. As soon as I do this it stops appearing in my list of plugins. No error occurs - it is like my plugin has vanished as soon as it has the dependency added.

I have registered my catalog against my unity container (which has already been fully registered/configured)

var catalog = new DirectoryCatalog("PluginFolder");
unityContainer.RegisterCatalog(catalog);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);

The plugin itself has its Unity-owned dependency specified like so

  [Import]
  public IUnityHostedThing MyThing { get; set; }

I have also tried the constructor injection like so

[ImportingConstructor]
public PluginA(IUnityThing thing)
{
    this.Mything = thing;
}

Neither approach works and either way the class no longer gets returned by the composition container stuff.

Any ideas? I haven't seen a good up to date example of this working with any actual implementations online - are there any?

cheers,
Robert

 

 


 

Oct 18, 2012 at 8:08 PM

Robert,

It this something like what you want?

(Note that the CompositionContainer is resolved from Unity BEFORE ComposeParts is called)

    [TestClass]
    public class MefUnityIntegrationTests
    {
... 
        [TestMethod]
        public void BasicMefUnityIntegrationTest()
        {
            var unityContainer = new UnityContainer();
            TypeRegistrationTrackerExtension.RegisterIfMissing(unityContainer);
 
            unityContainer.RegisterType<IUnityThingUnityThing>();
 
            var catalog = new AssemblyCatalog(typeof(MefUnityIntegrationTests).Assembly);
            unityContainer.RegisterCatalog(catalog);
            var mefContainer = unityContainer.Resolve<CompositionContainer>();
            mefContainer.ComposeParts(this);
 
 
 
            foreach (var plugin in MyPlugins)
            {
                this.TestContext.WriteLine("Plugin.Name = {0}  Plugin.Thing.Name = {1}", plugin.Name, plugin.Thing.Name); 
            }
        }
 
        [ImportMany(typeof(IPlugin))]
        public List<IPlugin> MyPlugins { getset; }
 
    }
 
    public interface IPlugin
    {
        string Name { get; }
        IUnityThing Thing { getset; }
    }
 
    [Export(typeof(IPlugin))]
    public class PluginA : IPlugin
    {
        public string Name { get { return "PluginA"; } }
 
        [Import]
        public IUnityThing Thing { getset; }
    }
 
    [Export(typeof(IPlugin))]
    public class PluginB : IPlugin
    {
        public string Name { get { return "PluginB"; } }
 
        [Import]
        public IUnityThing Thing { getset; }
    }
 
    public interface IUnityThing
    {
        string Name { get; }
    }
 
    public class UnityThing : IUnityThing
    {
        public string Name { get { return "UnityThing"; } }
    }
In any case, this particular example works for me, producing the following output...
Plugin.Name = PluginA  Plugin.Thing.Name = UnityThing
Plugin.Name = PluginB  Plugin.Thing.Name = UnityThing
Regards,
Ben