How to extend MEF to create objects based on the type of factory provided as an attribute?

Consider the following existing classes in which MEFs compose Consumer.

public interface IProducer
{
    void Produce();
}

[Export(typeof(IProducer))]
public class Producer : IProducer
{
    public Producer()
    {
        // perform some initialization
    }

    public void Produce()
    {
        // produce something
    }
}

public class Consumer
{
    [Import]
    public IProducer Producer
    {
        get;
        set;
    }

    [ImportingConstructor]
    public Consumer(IProducer producer)
    {
        Producer = producer;
    }

    public void DoSomething()
    {
        // do something
        Producer.Produce();
    }
}

However, the creation Producerhas become so complex that it can no longer be done inside the constructor, and the default behavior is no longer executed.

I would like to enter a factory and register it using my own FactoryAttribute for the manufacturer itself. Here is what I mean:

[Export(typeof(IProducer))]
[Factory(typeof(ProducerFactory))]
public class Producer : IProducer
{
    public Producer()
    {
        // perform some initialization
    }

    public void Produce()
    {
        // produce something
    }
}

[Export]
public class ProducerFactory
{
    public Producer Create()
    {
        // Perform complex initialization
        return new Producer();
    }
}

public class FactoryAttribute : Attribute
{
    public Type ObjectType
    {
        get;
        private set;
    }

    public FactoryAttribute(Type objectType)
    {
        ObjectType = objectType;
    }
}

If I had to write the β€œnew” code myself, it might look like this. It will use the factory attribute, if one exists, to create the part or the default for MEF to create it.

public object Create(Type partType, CompositionContainer container)
{
    var attribute = (FactoryAttribute)partType.GetCustomAttributes(typeof (FactoryAttribute), true).FirstOrDefault();
    if (attribute == null)
    {
        var result = container.GetExports(partType, null, null).First();
        return result.Value;
    }
    else
    {
        var factoryExport = container.GetExports(attribute.ObjectType, null, null).First();
        var factory = factoryExport.Value;
        var method = factory.GetType().GetMethod("Create");
        var result = method.Invoke(factory, new object[0]);
        container.ComposeParts(result);
        return result;
    }
}

There are a number of articles on how to implement ExportProvider, including:

,

  • Producer, IProducer. factory CompositionContainer.
  • Producer , factory CompositionContainer.
  • , , , CompositionContainer.

ExportProvider (, factory).

public class FactoryExportProvider : ExportProvider
{
    protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition,
                                                          AtomicComposition atomicComposition)
    {
        // What to do here? 
    }
}

, MEF factory, FactoryAttribute, , .

? MEF 2 Preview 5 .NET 4.

+3
1

:

public class ProducerExporter
{
   [Export]
   public IProducer MyProducer
   {
       get
       {
           var producer = new Producer();
           // complex initialization here
           return producer;
       }
   }
}

, factory , , , , . :

public class ProducerFactory
{
   [Export(typeof(Func<Type1,Type2,IProducer>)]
   public IProducer CreateProducer(Type1 arg1, Type2 arg2)
   {
       return new Producer(arg1, arg2);
   }
}

Func<Type1,Type2,IProducer>, , .

+3

All Articles