如何参数化我的出口?

时间:2012-11-22 21:30:23

标签: mef

我希望能够不仅使用类型(例如,通用导出)来参数化我的导出,还可以使用值。

类似的东西:

    class Greeter
    {
        readonly string _format;
        public Greeter( string format ) { _format = format; }

        public string Greet( string name ) { return string.Format( _format, name ); }
    }

    // ...

    var e = new ExportProvider();
    e.ExportParametrized<Greeter>( args: new[] { "Hi, {0}!" } );
    e.ExportParametrized<Greeter>( args: new[] { "¡Hola, {0}!" } );

    // And then:
    [ImportMany] IEnumerable<Greeter> Greeters { get; set; }

    foreach( var g in Greeters ) Console.WriteLine( g.Greet( "John" ) );

    // Should print out:
    //   Hello, John!
    //   ¡Hola, John!

有人可能会问:为什么我不只是使用new Greeter( "Hello, {0}!" )ComposablePartExportProvider导出价值CompositionBatch? 虽然这种方法适用于这种特殊情况,但它有一个重要的缺陷:如果Greeter类有任何自己的导入,它们就不会满意。

通常的做法是声明两个类 - EnglishGreeterSpanishGreeter,从Greeter继承它们,然后在对base的调用中提供适当的参数构造

但这有两个原因无效:

  1. 这要写很多噪音。我不仅需要输入整个shebang,我还必须为这些类提出名称,并且拥有名称并不总是有意义的。更不用说DRY原则了。但即使除了噪音......
  2. 有时候我不知道前面的参数。比方说,我的问候格式来自某种配置文件。
  3. 这是另一个想法,有点澄清我正在寻找的东西 这个问题在TypeCatalog几乎解决了。请参阅TypeCatalog了解类型,并调用类型的构造函数来按需创建零件 从另一个角度可以想到这个过程:目录具有工厂功能;使用该函数,它创建零件,然后满足其非先决条件导入,然后将零件返回给请求者。
    现在,在TypeCatalog的特定情况下,工厂函数恰好是类型自己的构造函数。如果我只能用我自己的工具挂钩并替换工厂功能,但仍然利用其余的机器,这正是我正在寻找的。

1 个答案:

答案 0 :(得分:2)

您可以使用属性导出来实现此目的。您可以专门为这些类型的导出定义一个类,它将如下所示:

class MyParameterizedExports
{
    [Export(typeof(Greeter))]
    private Greeter EnglishGreeter
    {
        get
        {
            Greeter g = new Greeter("Hi, {0}!");
            container.SatisfyImportsOnce(g);
            return g;
        }
    }

    [Export(typeof(Greeter))]
    private Greeter SpanishGreeter
    {
        get
        {
            Greeter g = new Greeter("¡Hola, {0}!");
            container.SatisfyImportsOnce(g);
            return g;
        }
    }
}

在这里,您可以导出两个单独的Greeter个实例,而无需为每种Greeter类型定义新类。