5

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

我还缺少其他方法吗?

4

3 回答 3

5

目前在 MEF 中没有直接的方法来执行此操作,但 MEF 团队正在考虑在 v.Next 中对此提供支持。您本质上想要创建相同实现的多个实例,这在传统上是使用工厂模式完成的。因此,您可以使用的一种方法是:

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));
    }
  }
}
于 2009-06-23T01:51:35.750 回答
4

MEF 预览版 8 对此提供了实验性支持,尽管它尚未包含在System.ComponentModel.Composition.dll. 有关更多信息,请参阅此博客文章

您必须下载 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>现在,如果需要动态创建零件,您的零件将能够导入 a Foo。编写自己的工厂类的优势在于,这将透明地处理 的导入Foo,以及导入的导入等。

编辑

  • MEF Preview 9 PartCreator中重命名为,ExportFactory但它仅包含在 silverlight 版本中。
  • MEF 2 Preview 2中,ExportFactory包含在桌面版中。因此ExportFactory可能会成为 .NET 4.0 之后的下一个 .NET 框架版本的一部分。
于 2009-12-26T01:48:58.650 回答
0

我相信这就是延迟导出功能的用途。从该页面:

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

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

于 2009-06-23T12:07:29.420 回答