Nuget 包不支持程序集版本的位数
Nuget pack does not honor number of digits on assembly version
我需要 nuget pack
来生成一个只有 3 位数字的包版本(我们想对其进行语义版本控制)但是当我在一个 AssemblyVersion
属性设置为的 csproj 上调用它时“1.0.0”,生成的 nupkg 文件在其元数据(和文件名)中以版本“1.0.0.0”结尾。为什么命令行工具不遵守 AssemblyVersion
属性中指定的位数?
我首先对 csproj 文件调用 nuget spec
,它会生成一个像这样的存根 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>
在与 csproj 文件相同的文件夹中的 TFS 中检查此 nuspec 文件后,我们现在可以像这样调用 pack:
nuget pack MyProject.csproj
项目的 AssemblyInfo.cs 文件包含明确设置版本的行:
[assembly: AssemblyVersion("1.0.0")]
除了该工具在检索程序集版本时使用 4 位数字之外,一切都运行良好。当我在文件资源管理器上右键单击 dll 并转到详细信息时,即使 Windows 显示的版本也只有 3 位数字。为什么 NuGet 使用 4 位数字?我是否遗漏了一些明显的东西?
在 nuspec 中对版本进行硬编码显然并不理想,因为那样的话我们将不得不在两个不同的地方维护版本号,而它们本应始终相同。我的意思是,这应该是特殊占位符值 $version$
背后的想法,NuGet 本身知道如何从项目中提取。
在 Creating and Publishing a Package 中指出,当使用标记 $version$
时,NuGet 使用 AssemblyVersionAttribute
属性。
深入研究 NuGet 源代码,我发现它并不像人们想象的那么简单。
NuGet 使用反射来获取库的版本。 AssemblyName.Version
确切地说。由于版本的所有组件都必须是大于或等于零的整数(请参阅 AssemblyName.Version),因此显示的版本是 1.0.0.0(在您的情况下)而不是在 AssemblyVersion
中声明的 1.0.0属性。
可能的解决方案
Nuspec Reference 页面在 $version$
标记旁边添加了更多信息。它提到 AssemblyInformationalVersionAttribute
属性将优先于 AssemblyVersionAttribute
。使用它会解决你的问题。
深入挖掘
您可能想知道为什么 AssemblyInformationalVersionAttribute
有效而 AssemblyVersionAttribute
无效?
这个问题的答案是 NuGet 使用 CustomAttributeData.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 class 的 public AssemblyMetadata GetMetadata(string path)
函数下找到。)
运行 进入同样的问题并使用 nuget 的“-version”属性解决了它。它会覆盖 nuspec 文件中的版本。非常适合语义版本控制。
根据以上情况,我猜在开始讨论时它还不可用。
NuGet 似乎使用 [assembly: AssemblyInformationalVersion()]
作为版本,而不是 AssemblyVersion
或 AssemblyFileVersion
将 AssemblyInformationalVersion
设置为 2 或 3 个组件,nuget 将完全按照您指定的方式打包它
我还将 AssemblyVersion
设置为一些 auto-incremented 东西,因为它被 .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 版本和简单的汇编版本(总是在变化,所以如果包版本保持不变,在构建过程中没有奇怪的缓存,比如本地测试)
我需要 nuget pack
来生成一个只有 3 位数字的包版本(我们想对其进行语义版本控制)但是当我在一个 AssemblyVersion
属性设置为的 csproj 上调用它时“1.0.0”,生成的 nupkg 文件在其元数据(和文件名)中以版本“1.0.0.0”结尾。为什么命令行工具不遵守 AssemblyVersion
属性中指定的位数?
我首先对 csproj 文件调用 nuget spec
,它会生成一个像这样的存根 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>
在与 csproj 文件相同的文件夹中的 TFS 中检查此 nuspec 文件后,我们现在可以像这样调用 pack:
nuget pack MyProject.csproj
项目的 AssemblyInfo.cs 文件包含明确设置版本的行:
[assembly: AssemblyVersion("1.0.0")]
除了该工具在检索程序集版本时使用 4 位数字之外,一切都运行良好。当我在文件资源管理器上右键单击 dll 并转到详细信息时,即使 Windows 显示的版本也只有 3 位数字。为什么 NuGet 使用 4 位数字?我是否遗漏了一些明显的东西?
在 nuspec 中对版本进行硬编码显然并不理想,因为那样的话我们将不得不在两个不同的地方维护版本号,而它们本应始终相同。我的意思是,这应该是特殊占位符值 $version$
背后的想法,NuGet 本身知道如何从项目中提取。
在 Creating and Publishing a Package 中指出,当使用标记 $version$
时,NuGet 使用 AssemblyVersionAttribute
属性。
深入研究 NuGet 源代码,我发现它并不像人们想象的那么简单。
NuGet 使用反射来获取库的版本。 AssemblyName.Version
确切地说。由于版本的所有组件都必须是大于或等于零的整数(请参阅 AssemblyName.Version),因此显示的版本是 1.0.0.0(在您的情况下)而不是在 AssemblyVersion
中声明的 1.0.0属性。
可能的解决方案
Nuspec Reference 页面在 $version$
标记旁边添加了更多信息。它提到 AssemblyInformationalVersionAttribute
属性将优先于 AssemblyVersionAttribute
。使用它会解决你的问题。
深入挖掘
您可能想知道为什么 AssemblyInformationalVersionAttribute
有效而 AssemblyVersionAttribute
无效?
这个问题的答案是 NuGet 使用 CustomAttributeData.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 class 的 public AssemblyMetadata GetMetadata(string path)
函数下找到。)
运行 进入同样的问题并使用 nuget 的“-version”属性解决了它。它会覆盖 nuspec 文件中的版本。非常适合语义版本控制。
根据以上情况,我猜在开始讨论时它还不可用。
NuGet 似乎使用 [assembly: AssemblyInformationalVersion()]
作为版本,而不是 AssemblyVersion
或 AssemblyFileVersion
将 AssemblyInformationalVersion
设置为 2 或 3 个组件,nuget 将完全按照您指定的方式打包它
我还将 AssemblyVersion
设置为一些 auto-incremented 东西,因为它被 .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 版本和简单的汇编版本(总是在变化,所以如果包版本保持不变,在构建过程中没有奇怪的缓存,比如本地测试)