我可以使用MEF控制对象创建吗?

时间:2009-06-22 14:29:18

标签: mef

我需要在现有代码中添加一些扩展点,我一直在将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],但是如何提供所需的种子?

我还缺少其他方法吗?

3 个答案:

答案 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的导入和导入的导入等。

修改

    {li} in MEF Preview 9 PartCreator已重命名为ExportFactory,但仅包含在silverlight版本中。
  • MEF 2 Preview 2中,ExportFactory包含在桌面版中。所以ExportFactory可能是.NET 4.0之后的下一个.NET框架版本的一部分。

答案 2 :(得分:0)

我相信这是Lazy Exports功能的用途。从该页面:

[Import]
public Export<IMessageSender> Sender { get; set; }
  

在这种情况下,您可以选择延迟此实例化,直到您确实需要实现实例。要请求实例,请使用方法[Export.GetExportedObject()]。请注意,此方法永远不会充当T实现的工厂,因此多次调用它将返回第一次调用时返回的相同对象实例。