打破 .NET MEF 导入链

发布于 2024-12-02 16:36:51 字数 1150 浏览 1 评论 0原文

对于此示例,您可以假设 toplevel 正在导入 ClassA。只要您导入所有内容(即 ClassX),MEF 似乎就可以很好地工作。通常您不需要导入,因为 classB 位于同一名称空间/文件中。结果,导入链现在被破坏,并且 myLog 导入永远不会组成。在我的示例中,ClassB 正在尝试导入记录器服务,这是几乎所有类都可能希望的。

如果有的话,哪一个是针对此问题的预期/最佳 MEF 解决方案?

1)一旦导入链被破坏,就不再使用导入。相反,您必须开始创建/将所有类型传递给构造函数(即 new ClassB(myLog))。这在本例中是有效的,但如果链中存在不使用参数的中间类,则会很混乱。

2)利用System命名空间中的IServiceLocator导入ClassB。据我所知,ServiceLocator(例如 Prism Framework)的存在只是为了抽象依赖注入方案。对于此示例,如果 ClassB 可以导入 IServiceLocator,那么它可以导入 ILogger。

3) 返回顶层调用 ComposeParts(ClassB)。为了防止顶层依赖于 ClassB,我可以让 classB 实现一个由顶层导入的接口 (IComposeMe)。然后顶层将在容器上为所有 IComposeMe 导入编写 ComposeParts。我不认为这是预期的解决方案,因为 MEF 框架文档中没有描述或使用它。

4)其实我没什么想法,请帮忙......

class ClassA {

  // Imports within ClassX will get composed
  [Import]
  ClassX myClassX;

  // Imports within ClassB will NOT be composed!
  var myClassB = new ClassB
}

class ClassB {

  // Fails because ClassB is never Composed
  [Import]
  ILogger myLog;

  myLog.Display("Hello World");
}

[Export]
class ClassX {

  // Works - Imports are satified when ClassX imported
  [Import]
  ILogger myLog;

  myLog.Display("Hello World");
}

For this example you can assume toplevel is importing ClassA. MEF seems to work great as long as you import everything (ie ClassX). Often you don't need to import because classB is in same namespace/file. As a result the import chain is now broken and myLog import is never composed. In my example ClassB is trying to import a Logger Service, which is something almost all classes might desire.

Which if any is the intended/best MEF solution to this issue?

1) Once import chain is broken never use import again. Instead you must start creating/passing all types to constructor (ie. new ClassB(myLog)). This works in this example but it is messy if there is intermediate classes in the chain not using the argument.

2) Make use of the IServiceLocator in the System namespace to import ClassB. As far as I know ServiceLocator (eg. Prism Framework) exist only to abstract the Dependency Injection scheme. For this example if ClassB could import the IServiceLocator then it could have imported ILogger.

3) Back at the toplevel call ComposeParts(ClassB). To prevent the toplevel from depending on ClassB I could have classB implement an Interface (IComposeMe), which the toplevel imports. Then the toplevel would ComposeParts on the container for all IComposeMe imports. I do not believe this is the intended solution, because it is not described or used in the MEF framework documentation.

4) Actually I am out of ideas, please help...

class ClassA {

  // Imports within ClassX will get composed
  [Import]
  ClassX myClassX;

  // Imports within ClassB will NOT be composed!
  var myClassB = new ClassB
}

class ClassB {

  // Fails because ClassB is never Composed
  [Import]
  ILogger myLog;

  myLog.Display("Hello World");
}

[Export]
class ClassX {

  // Works - Imports are satified when ClassX imported
  [Import]
  ILogger myLog;

  myLog.Display("Hello World");
}

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

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

发布评论

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

评论(2

猫腻 2024-12-09 16:36:51

如果遵循依赖注入模式,首选方法是什么? 不要破坏进口链。您的应用程序中应该有一个组合根,其中的组件连接在一起。组件本身不应该关心获取它们的依赖关系。

诚然,在实践中,您必须处理现有代码(以及其他对 DI 持怀疑态度的开发人员),因此您不能总是“一路向下”进行依赖项注入。在这些情况下,您可以将容器公开为全局变量,并从那里提取必要的依赖项。

将容器公开为全局容器本质上是服务定位器模式。但它有一些缺点

The preferred approach if you follow the dependency injection pattern? Don't break the import chain. You should have a single composition root in your application where the components are wired together. The components themselves shouldn't be concerned with acquiring their dependencies.

Granted, in practice you have to deal with existing code (and other developers sceptical of DI) so you can't always do dependency injection "all the way down". In those cases you can expose the container as a global variable and pull the necessary dependencies from there.

Exposing the container as a global is essentially the Service Locator pattern. It has some disadvantages though.

路还长,别太狂 2024-12-09 16:36:51

当然,您可以在某个地方注册您想要导入/导出的类型,而无需扫描整个程序集。
我不知道这是否有帮助,但这是我在谷歌搜索后发现的一个链接:
http://blogs.microsoft.co.il/blogs/zuker/archive/2010/10/17/mef-runtime-type-catalog-support-multi-registrations-in-runtime.aspx< /a>

Surely you can register somewhere which types you want to have imported/exported without having to scan the whole assembly.
I don't know if this will help but here's a link I found after googling a bit:
http://blogs.microsoft.co.il/blogs/zuker/archive/2010/10/17/mef-runtime-type-catalog-support-multi-registrations-in-runtime.aspx

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