Search code examples
.netdependenciesmefcomposition

MEF's ImportMany in the base class imports all exports from all assembles - how to prevent that?


I am using MEF to compose exported types from several assemblies. I'm using a base class, which should ImportMany dependencies, as specified in the derived classes. It looks something like this:

Base Assembly:

public abstract class BaseClass
{
    [ImportMany(typeof(IDependency)]
    public IEnumerable<IDependency> Dependencies { get; private set; }

    protected BaseClass()
    {
        var catalog = GetCatalog();
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
    }

    protected abstract ComposablePartCatalog GetCatalog();
}

Assembly A:

[Export(typeof(BaseClass))]
public class MyA : BaseClass
{
    protected override ComposablePartCatalog GetCatalog()
    {
        return new AssemblyCatalog(Assembly.GetExecutingAssembly());
    }
}

[Export(typeof(IDependency)]
public class DependencyA1 : IDependency {}

[Export(typeof(IDependency)]
public class DependencyA2 : IDependency {}

Assembly B:

[Export(typeof(BaseClass))]
public class MyB : BaseClass
{
    protected override ComposablePartCatalog GetCatalog()
    {
        return new AssemblyCatalog(Assembly.GetExecutingAssembly());
    }
}

[Export(typeof(IDependency)]
public class DependencyB1 : IDependency {}

[Export(typeof(IDependency)]
public class DependencyB2 : IDependency {}

I then compose everything in the base assembly:

static void Main(string[] args)
{
    DirectoryCatalog catalog = new DirectoryCatalog(path, "*.dll");
    var container = new CompositionContainer(catalog);
    IEnumerable<BaseClass> values = container.GetExportedValues<BaseClass>();

    // both BaseClass instances now have 4 Dependencies - from both Assemby A and Assembly B!
}

The problem I encounter, that when I use MEF to compose both MyA and MyB, each contain exported IDependency-ies from both assemblies! I only want MyA to contain exports DependencyA1 and DependencyA2, same with MyB.

I know I probably should be using a dependency injection container for this, but I was hoping it's possible to do with MEF?


Solution

  • Doing a composition under the nose of another composition is quite nasty ;).

    So I would resolve on calling container.GetExportedValues manually and set the property by yourself in the constructor that way you get rid of the [ImportMany] all together. and it is not being manipulated on the outer composition.

    HTH Ariel