16

这可能听起来像一个愚蠢的问题,但无论如何我都会试一试。

因此,在 Visual Studio 中,不能有两个项目 X 和 Y,使得 X 引用 Y,Y 引用 X。

总的来说,由于各种原因,我完全可以理解循环依赖是如何产生问题的。

但是这样编译两个相互依赖的项目真的不行吗?在我看来,这一定是可能的,因为(在我看来——也许我对此完全不了解)拥有两个相互依赖的程序集实际上与拥有两个相互依赖的类并没有太大区别——这种情况合法,可以编译。

如果您说“两个程序集不能相互依赖,因为编译器无法先编译一个”,这对我来说是有道理的;除了您似乎可以为同一个程序集中的两个类使用相同的参数,而且很明显编译器可以很好地处理这种情况。

基本上我问的原因不是我有做这件事的迫切愿望,我知道这通常是不明智的。具体来说,我想知道,因为如果我可以有两个项目——比如说,MyProjectCS 和 MyProjectVB——那就太好了——它们基本上作为一个单元的两个相互依赖的部分存在,并且只是因为某些部分是用 C# 编写的,所以它们是分开的。其他部分是用 VB.NET 编写的。

所以,我的问题是(哎呀,三倍):

  1. 是否可以启用此行为(就此而言,在 Visual Studio 或其他地方)?
  2. 如果在任何 IDE 中都不可能,至少在理论上是可能的,还是可能不存在相互依赖的程序集?
  3. 如果理论上都不可能,为什么不呢?换句话说,相互依赖的程序集与单个程序集中的相互依赖的代码有何不同?
4

5 回答 5

12

我不知道如何在 IDE 中做到这一点;但是,可以通过复杂的构建过程进行构建。

你会需要:

  1. 大会 A
  2. 大会 B
  3. 存根组件 B

其中 Stub Assembly B 包含 Assembly B 的公共类和公共方法以及相同的 AssemblyInfo.* 并引用相同的公钥。

构建顺序:

  1. 编译存根程序集 B
  2. 将存根程序集 B 复制到程序集 B 的输出目录
  3. 构建程序集 A
  4. 构建程序集 B

请注意,您不能在方法签名中直接循环引用类型;但是,您可以通过对象进行有效循环。

笔记:

ilasm 可以编译真正的相互递归程序集,因为它可以解析在编译时不存在的类型。

更远:

aspnet_compiler 似乎能够在同一个项目中混合不同的语言(谁知道如何)。

于 2010-07-03T01:26:27.163 回答
6

即使 mscorlib.dll 和 System.dll 程序集相互依赖,我建议永远不要有 2 个程序集相互依赖。

关于命名空间等铰链之间的依赖循环,我建议使用 NDepend 来检测和避免依赖循环

替代文字

文章摘录(我写的):控制组件依赖以获得干净的架构

组件之间的依赖循环导致了通常所说的意大利面条代码或纠结代码。如果组件 A 依赖 B 依赖 C 又依赖 A,则组件 A 不能独立于 B 和 C 进行开发和测试。 A、B 和 C 形成一个不可分割的单元,一种超级组件。由于规模不经济现象,这个超级组件的成本比 A、B 和 C 的成本总和要高(在软件估算:史蒂夫·麦康奈尔的《揭秘黑色艺术》中有详细记载)。基本上,这认为开发一段不可分割的代码的成本呈指数级增长。

这表明开发和维护 1,000 LOC(代码行)的成本可能是开发和维护 500 LOC 的三到四倍,除非它可以分成两个独立的块,每块 500 LOC。因此,与描述无法维护的纠结代码的意大利面条进行比较。为了使架构合理化,必须确保组件之间没有依赖循环,还要检查每个组件的大小是否可接受(500 到 1000 LOC)。

于 2010-08-29T19:13:38.577 回答
2

我不知道它在 VB 中是如何工作的,但理论上应该可以使用某种指向另一个的占位符(生成非法代码)来编译其中一个,然后用它来编译另一个,然后重新编译首先。

例如,当编译相互需要的程序时,循环依赖解析就是这样工作的。

--虽然通常这是通过禁用尚不存在的功能来完成的

于 2010-07-03T01:25:29.600 回答
1

如果您使用命令行工具构建,您可以拥有一个包含许多模块的程序集。每个模块都可以使用不同的编译器进行编译。模块之间可以有循环依赖。

但是,我不希望视觉工作室能够支持这一点。


您还可以采取一些技巧,告诉链接器将对类型的请求从一个程序集重定向到另一个程序集。Microsoft 使用这些,然后他们在 .net 框架内移动类型。仅当您无法让所有调用者重新编译那里的代码时,这才有价值。

于 2010-10-19T13:28:28.043 回答
0

如果使用条件编译,则 Visual Studio 中可能存在循环依赖关系。大多数情况下,最好从一开始就删除循环引用,但如果您有充分的理由保留它们,则可以将此解决方案用作构建它的解决方法。

于 2015-12-03T21:32:16.923 回答