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

发布于 2024-12-12 06:23:23 字数 1554 浏览 0 评论 0原文

所以,我正在尝试 MEF——有点尝试经典的 IoC 东西——注入一个日志记录类。 我让它工作了,但它没有按照我预期的方式工作。你能告诉我哪里偏离了轨道吗?

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

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

这是我的引导代码(在控制台应用程序的启动中):


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 类看起来像this:


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 始终为空。 -- 除非,我重复 Program.Main 执行的所有 MefInitialization 代码(或者,如果我将 Program 创建的容器设为公共静态,我可以调用 _Container.ComposeParts(this);

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

So, I'm playing around with MEF -- kind of trying a classic IoC thing -- injecting a logging class.
I have it working, but it is not working the way I expected it to work. Can you tell me where I'm off track?

I think that my problem is that I'm bootstrapping MEF incorrectly. I expected to Export a logger, and Import it to inject it into any class that wanted to use it.

What I'm finding is that for any class that wants to use it, I have to new up a container, load the catalogs, and call ComposeParts(). (which is actually a lot harder than just calling MyEventLogFactory.GetEventLog()). (I expected to have to bootstrap MEF once, on program init, but I seem to have to do it for every class that has in import)

Here's my bootstrap code (in the startup of a Console app):


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;
}

Then my TestHarness class looks like this:


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);
  }
}

My problem is that EventLog is always null. -- Unless, I repeat all of the MefInitialization code that Program.Main executed (or, if I make the container that Program created a public static, I can call _Container.ComposeParts(this);

So, my question: what is the right way to bootstrap MEF so that it satisfies all of my imports? Is it common practice to have a public static container and call Container.Compose(this)? (or to use AStaticContainer.GetExportedValue, sort of like you would use ServiceLocator.GetService()? inside all of my classes -- I definitely have not seen that in any sample code out there.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

找个人就嫁了吧 2024-12-19 06:23:24

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

我认为是这样的:

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 框架的原理类似。

I try to have as much as possible injected by the container in the bootstrap.

I think something like this:

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);
  }
}

This asks the container for the TestHarness instance, and it will import any dependencies as it instantiates it for you.

As far as keeping a reference to the container around, using singleton, static, servicelocator or whatever method of making it available, that is a similar principle to most other IoC frameworks when you need to ask them to resolve a type for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文