1
votes

I'm trying to figure out why one of my objects does not seem to be satisfying its Import. I think it may be the way I am using the container.ComposeParts() function but I have not been able to find much documentation with regards to it.

I have four projects
MEF.Service.Contracts
MEF.Service.Messaging (implements contracts)
MEF.Service.Core
MEF.Service.Console

MEF.Service.Contracts contains a simple interface called IMessageService with one function

public interface IMessageService
{
    void SendMessage(string message);
}

MEF.Service.Messaging has one implementation of the above

[Export(typeof(IMessageService))]
public class ConsoleMessageService : IMessageService
{
    #region IMessageService Members

    public void SendMessage(string message)
    {
        Console.WriteLine(message);
    }

    #endregion
}

MEF.Service.Core has a class called ServiceManager that imports available services. In this example the IMessageService

public class ServiceManager
{
    [Import]
    public IMessageService MessageService { get; set; }
}

Finally, in the MEF.Service.Console application project I am creating the MEF container using a DirectoryCatalog. Then I create an instance of ServiceManager and call its MessageService property.
However at this point it fails with an object reference error.

Here is the code in the MEF.Service.Console project

class Program
{
    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run();
    }

    public void Run()
    {
        Compose();

        ServiceManager manager = new ServiceManager();
        manager.MessageService.SendMessage("Test Message");

        Console.ReadLine();
    }

    private void Compose()
    {
        var catalog = new DirectoryCatalog(@".\");
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
    }
}

MEF.Service.Console has references to the other three projects just to ensure the dlls are in the same folder during runtime.

I've examined the catalog and container after they are initialized and it does contain my ConsoleMessageService export as a part.

I'm trying to figure out why my [Import] MessageService in my ServiceManager is not getting satisfied.

Any help or pointers on composing parts and how Imports get satified would be appreciated.

1

1 Answers

1
votes

I'm pretty new to MEF myself, but what I see here is this: you don't have the IMessageService as an instance of your main app - instead, it's on a separate object ServiecManager, that you create dynamically after the container.ComposeParts has been called...

My guess: MEF doesn't get a chance to satisfy the import on the ServiceManager since that object isn't around at the time of the composition.

Suggestion: add a IMessageService instance to your main app and let MEF handle the import, and then pass that instance into your ServiceManager - something like this:

class Program
{
    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run();
    }

    [Import]
    IMessageService MessageService { get; set; }

    public void Run()
    {
        Compose();

        ServiceManager manager = new ServiceManager(MessageService);
        manager.MessageService.SendMessage("Test Message");

        Console.ReadLine();
    }

    private void Compose()
    {
        var catalog = new DirectoryCatalog(@".\");
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
    }
}

I'm pretty sure if you do it this way, then MEF will be able to satisfy the import and you'll have yourself a MessageService instance which you can then pass into the ServiceManager.