Nuget pack不支持程序集版本上的位数

时间:2015-01-28 14:17:52

标签: nuget nuget-package nuget-spec

我需要nuget pack生成一个只有3位数的包版本(我们希望对其进行语义版本控制)但是当我在csproj上调用它时,{c <1}}属性设置为&# 34; 1.0.0&#34;,生成的nupkg文件以版本&#34; 1.0.0.0&#34;结尾在其中的元数据(和文件名)。为什么命令行工具不支持AssemblyVersion属性中指定的位数?

我是通过调用AssemblyVersion对csproj文件启动的,它生成了一个这样的存根nuspec文件(它实际上包含了带有占位符值的更多标签,但是我已经删除了它们,因为我们没有&# 39;不需要他们):

nuget spec

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

<?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>

项目的AssemblyInfo.cs文件包含一行显式设置版本:

nuget pack MyProject.csproj

除了工具在检索装配版本时使用4位数这一事实外,所有工作都完美无缺。当我右键单击文件浏览器上的dll并转到详细信息时,甚至Windows显示只有3位数的版本。为什么NuGet使用4位数字?我可能错过了一些明显的东西吗?

在nuspec中对版本进行硬编码显然不是理想的,因为那时我们必须将版本号保持在两个不同的位置,而它们的目的始终是相同的。我的意思是,这应该是特殊占位符值[assembly: AssemblyVersion("1.0.0")] 背后的想法,NuGet本身知道如何从项目中提取。

3 个答案:

答案 0 :(得分:9)

Creating and Publishing a Package中,声明NuGet在使用令牌AssemblyVersionAttribute时使用$version$属性。
深入研究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。 (该代码可以在public AssemblyMetadata GetMetadata(string path)类{{1}}下的{{1}}类中找到。)

答案 1 :(得分:1)

进入同样的问题并使用&#34; -version&#34;解决它。 nuget的属性。它会覆盖nuspec文件中的版本。非常适用于语义版本控制。

基于以上所述,我猜测在讨论开始时它是不可用的。

答案 2 :(得分:1)

NuGet似乎使用[assembly: AssemblyInformationalVersion()]作为版本,而不是AssemblyVersionAssemblyFileVersion

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版本和傻瓜证明程序集版本(如果软件包版本保持不变,那么在构建过程中总是会改变所以没有奇怪的缓存,比如本地测试)

Source