MEF and ABSTRACT FACTORY

UPDATE: Should I try to process it with a DI container or is this the wrong level of abstraction here?

I would like to implement ABSTRACT FACTORY using MEF (.NET 4.5).

This does not work for me ...

The composition remains unchanged. Changes were rejected due to the following errors (errors):

The composition produced a single compositional error. The main reason is given below. See the CompositionException.Errors property for more information.

1) Export not found, which corresponds to the restriction:

ContractName Mef3.Factory

RequiredTypeIdentity Mef3.Factory Result: Unable to set import "Mef3.Program._factory (ContractName =" Mef3.Factory ")" to the part "Mef3.Program".

Element: Mef3.Program._factory (ContractName = "Mef3.Factory") → Mef3.Program

Is this the right way to do this in MEF? How can I forward id to Foo / Bar ctors?

The code:

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

    readonly CompositionContainer _container;

    public Program()
    {
        var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
        _container = new CompositionContainer(catalog);
        _container.ComposeParts(this);
    }

    [Import]
    public Factory _factory;

    public void Run()
    {
        var foo = _factory.GetInstance("foo", 123);
        Console.WriteLine(foo is Foo);
    }
}

[Export]
public class Factory
{
    private readonly ExportFactory<Foo> _fooFactory;
    private readonly ExportFactory<Bar> _barFactory;

    [ImportingConstructor]
    public Factory(ExportFactory<Foo> fooFactory, ExportFactory<Bar> barFactory)
    {
        _fooFactory = fooFactory;
        _barFactory = barFactory;
    }

    public Base GetInstance(string name, int id)
    {
        switch (name)
        {
            case "foo":
                return _fooFactory.CreateExport().Value;

            case "bar":
                return _barFactory.CreateExport().Value;
        }

        throw new ArgumentException();
    }
}

public class Foo : Base
{
    [ImportingConstructor]
    public Foo([Import("Id")] int id)
    {
    }
}

public class Bar : Base
{
    [ImportingConstructor]
    public Bar([Import("Id")] int id)
    {
    }
}

[InheritedExport]
public abstract class Base
{
}
+5
source share
1 answer

The problem seems to be caused by your [Import ("Id")] on Foo and Bar. No export with contract name "Id". MEF as a whole does not allow you to import at runtime; you must be able to satisfy the entire graph at layout time, otherwise it will not work. If you want to use MEF to execute this particular scenario, you must remove the ImportingConstructor on Foo and Bar and add the SetId method in the base class and call factory when GetInstance is called.

+1
source

All Articles