错误 2 The type <T> exists in both... with ILMerge

Error 2 The type <T> exists in both... with ILMerge

我有 3 个项目:

依赖项是:

A 依赖于 B & C

B依赖C

并且 C 仅依赖于系统。

每个项目都有自己的命名空间。

只要没有安装 ILMerge,一切正常。

如果为项目 A ("A_MainProject") 激活了 ILMerge,一切仍然正常,并且为项目 A 生成了一个独立的可执行文件。

如果 ILMerge 现在也为 B_IntermediateProject 激活,我会收到以下错误:

Error   2   The type 'C_SharedClassLibrary.SharedClass' exists in both 'c:\dev\ILMergeError\B_IntermediateProject\bin\Debug\B_IntermediateProject.exe' and 'c:\dev\ILMergeError\C_SharedClassLibrary\bin\Debug\C_SharedClassLibrary.dll'    C:\dev\ILMergeError\A_MainProject\Program.cs    12  A_MainProject

我使用 "MSBuild ILMerge task" 1.0.3-rc2 和 "ILMerge" 2.13.0307(来自 mbarnett)。

最小解决方案包含 3 个项目,每个项目一个 class。 此版本仅在一个项目上激活了 ILMerge 并且有效:

ILMergeError_stillworking.zip

此版本也在项目 B 上激活并产生错误:

ILMergeError_error.zip

如果我将两个 exe 和 dll 与外部 ILMerge (ILMergeGUI) 合并,一切正常。

预先感谢您的回答, Xan-Kun

简短的回答是,您应该只在 A 上启用 ILMerge,它将 A+B+C 合并在一起。

您遇到此错误的原因是,当您在 B 上启用 ILMerge 时,B 也将使用所有 C 类型重新打包 (B' = B+C)。因此,当 ILMerge 在 A 上触发时,它将合并 A+B'+C = A+(B+C)+C

现在可能会发生 2 种情况:

  1. B 在内部使用 C,并且不(公开)公开任何 C 类型(例如作为方法参数或 return 值)。 在这种情况下,您可以通过 ILMerge 选项(B 上的 /internalize 和 A 上的 /allowDup)使其工作,尽管您最终会在合并的程序集 A 中使用每种 C 类型两次。

  2. B 公开了可能被 A 使用的 C 类型。 在这种情况下,即使您设法使合并工作,它也会在运行时失败,因为 A 和 B' 引用不同的类型(例如,对于 class c,B' 引用 B'.c 和 A 引用 C.c),你会得到讨厌的类型转换异常,因为它们是两种不同的类型(相同的名称,相同的命名空间,但不同的程序集)。

(它们很讨厌,因为它们不表示程序集不匹配,异常仅表示 "c cannot be cast to c",这可能会让很多人感到困惑)