考虑以下使用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,包括:
然而,这些例子并不理想,当
- 应用程序没有依赖关系或知识
Producer
,只有IProducer
. 创建时将无法注册工厂CompositionContainer
。 Producer
被多个应用程序重用,开发人员可能会在CompositionContainer
创建工厂时错误地忘记注册工厂。- 有大量类型需要自定义工厂,并且在
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。