6

我需要nuget pack生成一个只有 3 位数字的包版本(我们想对其进行语义版本控制)但是当我在属性设置为“1.0.0”的 csproj 上调用它时AssemblyVersion,生成的 nupkg 文件以版本“1.0”结尾.0.0" 在它的元数据(和文件名)中。为什么命令行工具不支持AssemblyVersion属性上指定的位数?

我首先调用了nuget spec对 csproj 文件的调用,该文件会生成一个像这样的存根 nuspec 文件(它实际上包含更多带有占位符值的标签,但我已经删除了它们,因为我们不需要它们):

<?xml version="1.0"?>
<package >
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>$author$</authors>
    <owners>$author$</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>$description$</description>
    <releaseNotes>Release notes.</releaseNotes>
    <copyright>Copyright 2015</copyright>
  </metadata>
</package>

将此 nuspec 文件签入 TFS 与 csproj 文件位于同一文件夹中后,我们现在可以像这样调用 pack:

nuget pack MyProject.csproj

项目的 AssemblyInfo.cs 文件包含明确设置版本的行:

[assembly: AssemblyVersion("1.0.0")]

一切都很好,除了该工具在检索程序集版本时使用 4 位数字。当我右键单击文件资源管理器上的 dll 并转到详细信息时,即使 Windows 也仅显示 3 位数的版本。为什么 NuGet 使用 4 位数字?我可能遗漏了一些明显的东西吗?

在 nuspec 中对版本进行硬编码显然并不理想,因为这样我们就必须在两个不同的地方维护版本号,而它们应该总是相同的。我的意思是,这应该是$version$NuGet 本身知道如何从项目中提取的特殊占位符值背后的想法。

4

3 回答 3

9

创建和发布包中,说明 NuGet在使用AssemblyVersionAttribute令牌时使用属性$version$
深入研究 NuGet 源代码,我发现它并不像人们想象的那么简单。

NuGet 使用反射来获取库的版本。AssemblyName.Version确切地说。由于版本的所有组件必须是大于或等于零的整数(请参阅AssemblyName.Version),因此呈现的版本是 1.0.0.0 (在您的情况下),而不是您的AssemblyVersion属性中声明的 1.0.0 。

可能
的解决方案Nuspec 参考$version$页面在令牌旁边添加了更多信息。它提到AssemblyInformationalVersionAttribute属性将优先于AssemblyVersionAttribute. 使用它将解决您的问题。

深入挖掘
您可能想知道为什么会AssemblyInformationalVersionAttribute起作用而不会起作用AssemblyVersionAttribute

该问题的答案是 NuGetCustomAttributeData.GetCustomAttributes(Assembly) 在使用 Assembly.Version 之前使用函数来检索库的属性。上面的函数不会列出AssemblyVersionAttribute,但AssemblyInformationalVersionAttribute如果在程序集中使用它会列出。只有这样,如果没有找到 AssemblyInformationalVersionAttribute,将使用 Assembly.Version。

编辑:
相关的 NuGet 源代码:
NuGet 使用以下代码获取程序集版本(如果未找到 AssemblyInformationalVersionAttribute):

Assembly assembly = Assembly.ReflectionOnlyLoadFrom(path);
AssemblyName assemblyName = assembly.GetName();
...
version = new SemanticVersion(assemblyName.Version);

问题从 assembly.GetName() 开始,因为它使用相关参数(包括版本)创建和初始化 AssemblyName。
(该代码可以在AssemblyMetadataExtractor类的public AssemblyMetadata GetMetadata(string path)函数下找到。)

于 2015-02-01T21:55:53.863 回答
2

遇到同样的问题并使用 nuget 的“-version”属性解决了它。它会覆盖 nuspec 文件中的版本。非常适合语义版本控制。

基于上述情况,我猜在开始讨论时它不可用。

于 2016-03-01T03:16:53.907 回答
1

NuGet 似乎被[assembly: AssemblyInformationalVersion()]用作一个版本,不是AssemblyVersion也不是AssemblyFileVersion

设置AssemblyInformationalVersion为 2 或 3 个组件,nuget 将完全按照您指定的方式打包它

我还设置AssemblyVersion了一些自动递增的东西,因为它被使用.NET并且根据我的MSBuild经验,强迫它一直认为版本变化更安全,所以它不会试图变得聪明

[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyInformationalVersion("1.0")]

结果是

Project.1.0.nupkg

包含

Project.dll

带有元数据(由 ILSpy 报告)..., Version=1.0.6246.25505, Culture=neutral, PublicKeyToken=null...

所以你会得到很好的 nuget 版本和万无一失的汇编版本(如果包版本保持不变,那么在构建过程中总是会发生变化,所以不会出现奇怪的缓存,比如本地测试)

资源

于 2017-02-06T22:19:53.507 回答