3

考虑以下使用MEF组合的现有类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();
    }
}

但是,创建Producer已经变得足够复杂,无法再在构造函数中完成,默认行为也不再足够。

我想介绍一个工厂并使用生产者本身的自定义 FactoryAttribute 注册它。这就是我的想法:

[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;
    }
}

如果我必须自己编写“新”代码,它可能看起来如下所示。它将使用工厂属性(如果存在)来创建零件,或者默认使用 MEF 来创建它。

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;
    }
}

有许多文章如何实现 ExportProvider,包括:

  1. 使用导出提供程序的 MEF + 对象工厂
  2. 动态实例化

然而,这些例子并不理想,当

  1. 应用程序没有依赖关系或知识Producer,只有IProducer. 创建时将无法注册工厂CompositionContainer
  2. Producer被多个应用程序重用,开发人员可能会在CompositionContainer创建工厂时错误地忘记注册工厂。
  3. 有大量类型需要自定义工厂,并且在CompositionContainer创建工厂时记住注册工厂可能会带来维护噩梦。

我开始创建一个 ExportProvider(假设这将提供使用工厂实现构造的方法)。

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

但是,我无法理解如何告诉 MEF 使用 FactoryAttribute 中定义的工厂对象,如果不存在此类属性,则使用默认创建机制。

执行此操作的正确方法是什么?我正在使用MEF 2 Preview 5和 .NET 4。

4

1 回答 1

3

您可以使用属性导出

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

请注意,工厂一词并不真正适合您的示例,我将保留该术语以用于进口商想要随意创建实例的情况,可能通过提供一个或多个参数。这可以通过方法 export来完成:

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>您可以随意调用以创建新实例的实例。

于 2012-05-06T10:22:13.313 回答