在两个项目中的引用

11
我有两个项目,分别是P1P2

P1P2的引用(reference)

这样我就可以从P1访问P2的方法(methods)。但如果我想从P2访问P1的方法,该怎么办呢?

我知道我不能在P2中添加P1的引用

如果可以的话,那么怎么做呢?
4个回答

20

正如其他人指出的一样,循环引用是问题所在。在编译P1之前它不能编译P2,但如果P1依赖于P2,那么在P2编译之前它又无法编译P1...明白问题了吗?

现在解决方案:

  • 简单粗暴法:创建一个共享库,将P1和P2的共享代码放入其中。这个共享项目可以被P1和P2同时引用。

  • 更好的解决方案:创建一个接口,在共享库中定义它。在P1中基于共享接口的“引用”,而不是实际的实现,来引用P2。以这种方式,您将获得一个更易于测试的解决方案,并且更容易替换您代码的某些部分。


3

简短回答:无法将 P1 作为引用添加到 P2 项目中,因为这将创建一个不允许的循环依赖关系。考虑重构代码并以不同的方式设计应用程序。一种方法是引入另一个项目,该项目包含对两个项目的引用。


3
另一种实现方法是在解决方案中将P1作为项目引用P2,但P2仅引用其输出的DLL或EXE作为P1的引用。这样会失去一些跨项目/依赖项检查,但确实可以进行交叉引用。
我曾经在一个长期运行的WinForms应用程序中使用过这种方法。该应用程序最初是用VB编写的,但几年后转移到了C#。所有新的Windows窗体都是用C#编写的,这不可能与VB窗体相同的项目,但某些VB窗体需要调用新的C#窗体,反之亦然。
编辑1:
其中的一个缺点是,如果P2将P1设置为其输出的DLL/EXE项目引用,然后在清理/重新构建解决方案时出现错误,您就处于这样的位置:输出的DLL/EXE不再存在,并且无法在解决错误之前重新创建,但解决方案却无法构建,因为它缺少一个引用。这不是一个好的状态,因此请确保定期备份输出的DLL/EXE以防万一。

哦,我一定会尝试这种方法。 - Naila Akbar
通过双向链接两个程序集,您使得这些程序集彼此之间永远无法独立工作(失去了代码可重用性),但如果您想在应用程序和DLL之间共享诸如日志记录(以及状态信息的显示)等内容,则另一种选择是复制逻辑(违反DRY原则)。从概念上讲,例如,一个DLL不应该依赖于使用它的应用程序,但另一方面,拥有两个单独的日志文件会使“在应用程序中执行X导致在DLL中发生Y”的情况变得不太清晰。 - jrh
在我看过的C/C++代码中,这种链接方式并不总是可以避免的,而且也并不罕见,这可能取决于你最初为什么要创建一个单独的DLL,如果我没记错,Quake 3就是通过这种方式在其(可替换的)引擎组件之间进行通信的。 - jrh
4
@jrh - 我同意你的看法,但在我的情况下,我们决定在大约8年后改变语言。这两个项目在逻辑上是一个单一的项目,但由于我无法在同一个项目中同时使用C#和VB,因此这是一个解决方法。 - Jon Roberts
@JonRoberts 对的,我主要是决定发表评论,因为我可以想到一些需要具有类似循环引用的情况,并且我认为并不是每个程序集都必须像可重用库dll一样运行。我认为“共享代码”答案做出了很多假设,我可以想到对于彼此相互依赖的非可重用dll的有效用途;对于那些真正需要的情况,您可以重构到时间结束,但问题只会转移到其他地方。 - jrh

1

你不能从P2引用P1,因为这会创建循环依赖。循环依赖指向糟糕的设计。有一些解决方法,例如可以将共享代码重构到另一个项目中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接