MEF - 我似乎在这里遗漏了一些东西

时间:2011-10-27 00:21:35

标签: c# mef

所以,我正在玩MEF - 有点尝试经典的IoC - 注入一个日志类。 我有它工作,但它没有像我期望的那样工作。你能告诉我我在哪里偏离轨道吗?

我认为我的问题是我错误地引导了MEF。我期望导出一个记录器,并导入它以将其注入任何想要使用它的类。

我发现,对于任何想要使用它的类,我必须新建一个容器,加载目录,然后调用ComposeParts()。 (这实际上比调用MyEventLogFactory.GetEventLog()更难。 (我希望在程序初始化时必须引导MEF一次,但我似乎必须为导入的每个类都执行此操作)

这是我的引导代码(在启动Console应用程序时):


static void Main(string[] args)
{
    InitMefContainer();
    var test = new TestHarness();
    test.RunTest();

    Console.ReadLine();
}

private static void InitMefContainer()
{
    var catalog = new AggregateCatalog();
    catalog.Catalogs.Add(new AssemblyCatalog(typeof(EventLogFactory).Assembly));
    catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
    var container = new CompositionContainer(catalog);
    container.ComposeParts();
    _Container = container;
}

然后我的TestHarness类看起来像这样:


public class TestHarness
{
  [Import(typeof(IEventLog))]
  public IEventLog EventLog { get; set; }

  public void RunTest()
  {
     // did not expect to need to do this, but EventLog is null if I don't
     Program._Container.ComposeParts(this);

     this.EventLog.Write(some test event stuff);
  }
}

我的问题是EventLog始终为null。 - 除非,我重复Program.Main执行的所有MefInitialization代码(或者,如果我创建一个程序创建公共静态的容器,我可以调用_Container.ComposeParts(this);

所以,我的问题是:什么是引导MEF的正确方法,以便它满足我的所有导入?通常的做法是拥有一个公共静态容器并调用Container.Compose(this)? (或者使用AStaticContainer.GetExportedValue,有点像你在我的所有类中使用ServiceLocator.GetService()?我绝对没有在任何示例代码中看到过。

1 个答案:

答案 0 :(得分:2)

我尝试尽可能多地将容器注入引导程序中。

我认为是这样的:

static void Main(string[] args)
{
    InitMefContainer();

    var test = _Container.GetExportedValue<TestHarness>();
    test.RunTest();

    Console.ReadLine();
}

private static void InitMefContainer()
{
    var catalog = new AggregateCatalog();
    catalog.Catalogs.Add(new AssemblyCatalog(typeof(EventLogFactory).Assembly));
    catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
    var container = new CompositionContainer(catalog);
    container.ComposeParts();
    _Container = container;
}

[Export]
public class TestHarness
{
  [Import(typeof(IEventLog))]
  public IEventLog EventLog { get; set; }

  public void RunTest()
  {
     // did not expect to need to do this, but EventLog is null if I don't

     this.EventLog.Write(some test event stuff);
  }
}

这会向容器询问TestHarness实例,它会在为您实例化时导入所有依赖项。

至于保持对容器的引用,使用单例,静态,服务定位器或任何使其可用的方法,这是大多数其他IoC框架的类似原则,当您需要让他们为您解析类型时