依赖注入可以防止循环依赖吗?

mrb*_*lah 3 c# assemblies dependency-injection circular-dependency

项目#1有一些项目#2引用的接口和类.

现在我想在Project#1中使用Project#2的实现,但vs.net抱怨循环依赖.

如果我在Project#1中使用依赖注入并绑定到Project#2中的实现(因为它遵守接口契约),这是否可行或者我仍然会在运行时获得循环依赖性错误消息?

Aar*_*ght 15

你可能用DI 来解决这个问题,但你不应该这样做.

如果我理解正确,你会有这样的事情:

  + Assembly A           + Assembly B
  |                      |
  +-- Interface IFoo     +-- Class ConcreteFoo : IFoo
  |                                   ^
  +-- Class MyClass -->------->-------|

换句话说,你正在试图获得MyClass引用ConcreteFoo,但你不能因为程序集B,其中ConcreteFoo居住在已经依赖于IFoo中A.

这是一个设计错误.如果IFoo在Assembly中声明接口A,但没有具体的实现,那么程序集中的任何其他接口/类A应该只引用IFoo,而不是实现它的具体类.

有三种方法可以消除循环依赖:

  1. 让MyClass依赖IFoo的替代ConcreteFoo.如果你能做到这一点,这可能是最好的选择.如果问题是你需要一个物理实例IFoo供使用MyClass而且不知道从哪里获取一个,那么让它IFoo在构造函数中使用 - 让任何人使用MyClass弄清楚IFoo要使用的内容.

  2. 将接口移动到自己的程序集.这仍然是一个相当不错的做法.您的设计将如下所示:

      + Assembly App       + Assembly Interfaces      + Assembly Concrete
      |                    |                          |
      |                    +-- Interface IFoo         |
      |                    |                  \       |
      +-- Class MyClass    |                   \------+-- Class ConcreteFoo
      |                    |                          |           ^
      +---- Member Foo ->--------------------->-------------------|
    
  3. 移动MyClass到自己的程序集.实际上,您的依赖树看起来与上面的#2相同,但如果汇编A比B那时小得多,则需要更少的工作量.

希望有所帮助.


Mar*_*ann 8

您通常可以使用抽象工厂通过依赖注入(DI)解决循环依赖性问题.请看这里的例子.

但是,尽管您可以通过DI解决问题,但最好重新设计API以使循环依赖性消失.

您通常可以通过将基于查询的API之一更改为基于事件的 API来打破循环依赖关系.