项目#1有一些接口和类,用于投射#2引用。
现在我想在Project#1中使用Project#2的实现,但vs.net抱怨循环依赖。
如果我要在Project#1中使用依赖注入并绑定到Project#2中的实现(因为它遵守接口契约),这是否可行或者我仍会在运行时获得循环依赖性错误消息?< / p>
答案 0 :(得分:15)
你可能可以用DI来解决这个问题,但你不应该。
如果我理解正确,你会有这样的事情:
+ Assembly A + Assembly B | | +-- Interface IFoo +-- Class ConcreteFoo : IFoo | ^ +-- Class MyClass -->------->-------|
换句话说,您试图让MyClass
引用ConcreteFoo
,但您不能,因为B
所在的汇编ConcreteFoo
已经取决于在IFoo
的{{1}}上。
这是一个设计错误。如果在Assembly A
中声明接口IFoo
,但没有具体实现,那么程序集A
中的任何其他接口/类应仅引用{{1} },从不实现它的具体类。
有三种方法可以消除循环依赖:
让A
取决于IFoo
而不是MyClass
。如果你能做到这一点,这可能是最好的选择。如果问题是您需要在IFoo
中使用ConcreteFoo
的物理实例并且不知道从哪里获取,请在构造函数中使用IFoo
- 让使用MyClass
的任何人都会找出IFoo
要使用的内容。
将接口移动到自己的程序集。这仍然是一个相当不错的做法。您的设计将如下所示:
+ Assembly App + Assembly Interfaces + Assembly Concrete | | | | +-- Interface IFoo | | | \ | +-- Class MyClass | \------+-- Class ConcreteFoo | | | ^ +---- Member Foo ->--------------------->-------------------|
将MyClass
移至自己的程序集。有效地,您的依赖关系树看起来与上面的#2相同,但如果汇编IFoo
远小于MyClass
,那么这将需要更少的工作量。
希望有所帮助。
答案 1 :(得分:8)
您通常可以使用抽象工厂解决依赖注入(DI)的循环依赖性问题。请参阅here for an example。
但是,尽管您可以通过DI解决问题,但最好重新设计API以使循环依赖性消失。
您通常可以通过将基于查询的API中的一端更改为基于事件的 API来打破循环依赖。
答案 2 :(得分:1)
只要你在Project 1代码中只使用Project 1中的类和接口,你就可以了。 (我假设依赖注入的配置是在Project 1的代码库之外完成的。)
但是我还要说,任何循环依赖的存在都会引导你质疑它为什么存在,并提示其他方法来解决消除它的问题。