6

在我们的商店中,我们使用 Cruise Control 和 MSBuild 来自动化产品的构建,作为持续集成的一部分。

构建的一部分是对程序集进行签名,以便它们具有强名称。

在我们本地开发的项目文件中,它没有指定签名,因为它被 MSBuild 脚本覆盖。

这一切都很好,直到我决定要引入需要我使用该InternalsVisibleTo属性的单元测试。我还开始使用一个不错的开源库,其中包含也使用这种技术的单元测试。

这意味着,在我的机器上,我可以更新AssemblyInfo.cs以使用以下语句:

[assembly: InternalsVisibleTo("MyProject.Tests.UnitTests")]

一切都很好。

但是,检查这个会破坏构建,因为构建机器对程序集进行签名,该行需要更新为如下所示:

[assembly: InternalsVisibleTo("MyProject.Tests.UnitTests, 
             PublicKey="magic key here..)"]

我有一半的想法是不签署集会并收工。但是,“签署程序集是最佳实践”(重复此咒语 3 次),如果我们从中获得任何好处,我不想远程处理它。

我们不安装到 GAC,我们并不特别担心篡改,不必担心使用我们库的第三方,我们在更新应用程序时会立即更新所有文件。最明显的好处是支持人员无法将程序集的某些随机版本复制到运行时文件夹中,并且让事情看起来可以工作一段时间。

我不想打开涉及手动更改大约 100 个项目文件以启用签名的作品。我也不想通过将应该是内部的东西标记为公共来破坏东西,我不想进入绑定重定向并且我不想删除单元测试。

我希望没有强名称的所有便利以及拥有强名称的所有好处(如果有的话),我不想为此做很多额外的工作。那是过分的要求?

这篇文章很好地描述了问题和解决方案,但我不是一个 MSBuild 脚本专家来利用它:

http://social.msdn.microsoft.com/forums/en-US/msbuild/thread/02df643c-956a-48bd-ac01-4a1016d91032/

这个问题的正确解决方案是什么?

欢迎任何意见和讨论点。

4

2 回答 2

5

使用您用来禁用签名开发人员构建的相同构造来定义编译器符号,例如。DO_NOT_SIGN,然后,在你的AssemblyInfo.cs,使用这个:

#if DO_NOT_SIGN
[assembly: InternalsVisibleTo("MyProject.Tests.UnitTests")]
#else
[assembly: InternalsVisibleTo("MyProject.Tests.UnitTests, PublicKey="magic key here..)"]
#endif

在我个人看来,它比从构建脚本修改源代码更优雅。

于 2011-06-25T13:41:13.873 回答
4

您可以在编译之前将关键信息修补到源文件中。

以下示例使用FileUpdate来自MSBuild 社区任务和(非常粗略的)正则表达式将关键信息修补到 C# AssemblyInfo.cs 文件中。

<ItemGroup>
    <AssemblyInfoFiles Include="$(MSBuildProjectDirectory)**/AssemblyInfo.cs"/>
</ItemGroup>
<FileUpdate
  Files="@(AssemblyInfoFiles)"
  Regex='(\[assembly:\s*InternalsVisibleTo\(\"[\w.]*\")(\)\])'
  ReplacementText='$1, PublicKey="$(StrongNamingPublicKey)"$2' />

但是,我认为将项目修改为始终使用强名称符号将是消除开发环境和部署环境之间的另一个差异的更简洁的解决方案,并且可以轻松编写脚本。

于 2011-06-25T10:51:41.253 回答