我需要在现有代码中添加一些扩展点,我一直在将MEF视为可能的解决方案。我们有一个IRandomNumberGenerator接口,我们希望可以交换默认实现(ConcreteRNG)。这听起来像MEF的理想情况,但我一直遇到实例化随机数生成器的问题。我们当前的代码如下:
public class Consumer
{
private List<IRandomNumberGenerator> generators;
private List<double> seeds;
public Consumer()
{
generators = new List<IRandomNumberGenerator>();
seeds = new List<double>(new[] {1.0, 2.0, 3.0});
foreach(var seed in seeds)
{
generators.Add(new ConcreteRNG(seed));
}
}
}
换句话说,消费者负责实例化所需的RNG,包括提供每个实例所需的种子。
我想要做的是让MEF发现并实例化具体的RNG实现(使用DirectoryCatalog)。我不知道如何实现这一目标。我可以公开Generators属性并将其标记为[Import],但是如何提供所需的种子?
我还缺少其他方法吗?
答案 0 :(得分:5)
目前在MEF中没有直接的方法,但MEF团队正在考虑在v.Next中对此进行支持。您基本上想要创建使用Factory模式传统完成的同一实现的多个实例。因此,您可以使用的一种方法是:
public interface IRandomNumberGeneratorFactory
{
IRandomNumberGenerator CreateGenerator(int seed);
}
[Export(typeof(IRandomNumberGeneratorFactory))]
public class ConcreateRNGFactory : IRandomNumberGeneratorFactory
{
public IRandomNumberGenerator CreateGenerator(int seed)
{
return new ConcreateRNG(seed);
}
}
public class Consumer
{
[Import(typeof(IRandomNumberGeneratorFactory))]
private IRandomNumberGeneratorFactory generatorFactory;
private List<IRandomNumberGenerator> generators;
private List<double> seeds;
public Consumer()
{
generators = new List<IRandomNumberGenerator>();
seeds = new List<double>(new[] {1.0, 2.0, 3.0});
foreach(var seed in seeds)
{
generators.Add(generatorFactory.CreateGenerator(seed));
}
}
}
答案 1 :(得分:4)
MEF预览8虽然尚未包含在System.ComponentModel.Composition.dll
中,但已为此提供实验支持。有关详细信息,请参阅this blog post。
您必须下载MEF源并构建解决方案。在Samples\DynamicInstantiation
文件夹中,您将找到程序集Microsoft.ComponentModel.Composition.DynamicInstantiation.dll
。添加对此程序集的引用,并向容器添加动态实例化提供程序,如下所示:
var catalog = new DirectoryCatalog(".");
var dynamicInstantiationProvider = new DynamicInstantiationProvider();
var container = new CompositionContainer(catalog, dynamicInstantiationProvider);
dynamicInstantiationProvider.SourceProvider = container;
现在,如果需要动态创建PartCreator<Foo>
部件,您的部件将能够导入Foo
。编写自己的工厂类的优势在于,它将透明地处理Foo
的导入和导入的导入等。
修改强>:
PartCreator
已重命名为ExportFactory
,但仅包含在silverlight版本中。
ExportFactory
包含在桌面版中。所以ExportFactory
可能是.NET 4.0之后的下一个.NET框架版本的一部分。答案 2 :(得分:0)
我相信这是Lazy Exports功能的用途。从该页面:
[Import]
public Export<IMessageSender> Sender { get; set; }
在这种情况下,您可以选择延迟此实例化,直到您确实需要实现实例。要请求实例,请使用方法[Export.GetExportedObject()]。请注意,此方法永远不会充当T实现的工厂,因此多次调用它将返回第一次调用时返回的相同对象实例。