在我们的公司,我们使用 NuGet 来版本化我们的内部库。对库的每次提交都会触发构建服务器,该服务器会生成新的 NuGet 包并将其上传到我们的内部源。
这对我们来说效果很好,但我们经常遇到 WinForms 设计器的问题,它会拒绝加载带有如下错误消息的表单:
Die Datei oder Assembly "UILib, Version=1.0.0.906, Culture=neutral, PublicKeyToken=null" oder eine Abhängigkeit davon wurde nicht gefunden. Das System kann die angegebene Datei nicht finden.
(大致:找不到文件或程序集“UILib,Version=1.0.0.906,Culture=neutral,PublicKeyToken=null”或其依赖项之一。系统找不到此文件。)
但这只是设计者的问题 - 应用程序将毫无问题地构建并按预期运行。
这就是问题所在,但现在您需要一些有值(value)的上下文才能理解它。我尝试打开的表单是应用程序的一部分(我们称之为应用程序),它包含一个 UserControl,它是我们特定于产品的 UI 库 (ProductUILib) 的一部分。该库又引用我们的通用 UI 库 (UILib)。但是,应用程序本身也直接依赖于 UILib。
UILib 和 ProductUILib 都是通过它们自己的 NuGet 包提供的。所以,简化的依赖图是这样的:
App ----> ProductUILib ----> UILib
| ^
------------------------------|
只要 ProductUILib 和 App 引用相同版本的 UILib(例如 1.0.0.906),一切都很好。但是,如果我修改 UILib,然后更新 App 中的 NuGet 依赖项,App 将获取并引用最新版本的 UILib(例如 1.0.0.932)。 ProductUILib 是针对旧版 UILib 构建的,但这应该没问题,因为对 UILib 的所有更改都是向后兼容的,而且我们也没有为这些库提供强名称。事实上,构建和运行应用程序效果很好。但受影响的表单现在设计器已损坏,并显示我上面提到的错误消息。
为了解决这个问题,我们还必须更新 ProductUILib 的 NuGet 包,以便它依次针对最新的 UILib 进行构建,然后再次更新 App 的依赖项以获得新的 ProductUILib。但这很快就会变得乏味,尤其是在有更多库和依赖项的情况下。
我在 VS 2010 和最新的 VS 2013 中进行了测试,新的显示了完全相同的行为。
您对我们如何避免此问题有什么建议吗?
最佳答案
我们通过更改使用 AssemblyVersion
、AssemblyFileVersion
和 AssemblyInformationalVersion
的策略成功解决了该问题。
我们会在每次构建时自动生成版本号的最后一部分,并将其设置为当前的 SVN 修订号。此生成的版本号(例如 1.0.0.906)用于进入 AssemblyVersion
和 AssemblyFileVersion
。
设计者显然对 AssemblyVersion
不匹配存在疑问,因为具有不同 AssemblyVersion
的程序集被视为不兼容。但是,没有强名称的程序集的正常加载过程不会介意不匹配,因此构建和运行程序是有效的。所以设计师只是比较挑剔而已。
解决方案是使用 AssemblyVersion
的固定值,我们只会在重大更改时更新该值。生成的版本号现在同时转到 AssemblyFileVersion
和 AssemblyInformationalVersion
。最后一个很重要,因为 NuGet 将始终从 AssemblyVersion
填充其 .nuspec $version$ 占位符,除非存在 AssemblyInformationalVersion
来覆盖它,并且我们希望生成的版本号为用于我们的 NuGet 包。
总结一下:
- 仅更新
AssemblyVersion
进行重大更改 - 使用
AssemblyInformationalVersion
作为应放入 NuGet 包的编号
关于winforms - 如何使用 NuGet 工作流程避免因程序集版本不匹配而导致的 Winforms 设计器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26262354/