Search code examples
c#dependency-injectionnullmef

MEF Import is null


I have an Import that is not working - the object is null. Originally it was an ImportMany but I simplified it down to an Import to try to identify the issue but I haven't been successful in doing so.

I've gone through this site and Google and followed the main ideas:

  • Don't instantiate the class yourself, let MEF do it, otherwise call container.getExport() - still doesn't work
  • Put an [Export] on the class containing the [Import] property otherwise it won't be picked up as a part by the container composition process (confirmed when debugging).

My code set up is as follows (simplified for the sake of compactness):

Assembly1

public class MyBootstrapper
{
    //Automatically called by ExcelDna library, I do not instantiate this class
    public void AutoOpen()
    {
        var ac1 = new AssemblyCatalog(typeof(XLHandler).Assembly);
        var ac2 = new AssemblyCatalog(typeof(MyComponent).Assembly);

        var agc = new AggregateCatalog();
        agc.Catalogs.Add(ac1);
        agc.Catalogs.Add(ac2);

        var cc = new CompositionContainer(agc);

        try
        {
            cc.ComposeParts(this);
        }
        catch (CompositionException exception) {}
    }
}

[Export]
public class XLHandler
{
    [Import(typeof(IMyComponent))]
    public IMyComponent _component;

    public void SomeMethod()
    {
        //try to use _component but it is null
    }
}

Assembly2

public interface IMyComponent
{
    //stuff...
}

Assembly3

[Export(typeof(IMyComponent)]
public MyComponent : IMyComponent
{
    //more stuff...
}

Anybody know/have an idea as to why the _component variable in XLHandler is not injected into by the MEF container?

Do I need to Export/create an AssemblyCatalog for the Interface in Assembly2?


Solution

  • When importing parts, you can either use the [Import] attribute on a Property, or request it as part of the Constructor and use an [ImportingConstructor] attribute.

    Any part imported using the [Import] attribute will not be available in the class's constructor

    So in your case, change the XLHandlerclass like this:

    [Export]
    public class XLHandler
    {
        [ImportingConstructor]
        public void SomeMethod(MyComponent component)
        {
            _component = component;
           // You can use _component, since it has already been resolved...
        }
    }