如何避免 .NET AssemblyVersion 和 AssemblyFileVersion 中的重复常量字符串

How to avoid repeated constant string in .NET AssemblyVersion and AssemblyFileVersion

在 C# 项目中,我们手动增加版本并有一个顶级文件 MyAssemblyInfo.cs 包含

[assembly: AssemblyVersion("31.1.13")]
[assembly: AssemblyFileVersion("31.1.13")]
[assembly: AssemblyInformationalVersion("31.1.13-V1.0.0")]

我想避免重复版本。例如,对于 C 预处理器,可以将其写为

#define VERSION "31.1.13"
[assembly: AssemblyVersion(VERSION)]
[assembly: AssemblyFileVersion(VERSION)]
[assembly: AssemblyInformationalVersion(VERSION "-V1.0.0")]

有没有办法在不使用任何外部工具的情况下在 C# 中实现此目的?

[assembly: AssemblyFileVersion(AppVersion.Version)]
[assembly: AssemblyInformationalVersion(AppVersion.Version)]
// you can use + here but the format you use shows as invalid version for me
[assembly: AssemblyVersion(AppVersion.Version)] 

// this must be at the end of the global declarations
internal class AppVersion
{
    public const string Version = "31.1.13";
}

对您的问题的简短回答是您不能以这种方式使用预处理器指令。另一个答案中说明了一种解决方法,涉及定义一个常量。这可能是旧式项目的唯一解决方案。

但是,如果您使用的是 SDK 样式的项目格式,则可以在项目文件中设置 AssemblyInfo 属性。以下属性对应于上面定义的属性:

  • InformationalVersion -> AssemblyInformationalAttribute
  • AssemblyVersion -> AssemblyVersion
  • FileVersion -> AssemblyFileVersion
  • Version -> 如果它们被省略,可以映射到上面的 any/all
    • 在设置File/Assembly版本
    • 时有特殊逻辑删除后缀模式

所有其他 Assembly attributes 都可以通过属性设置,只要 GenerateAssemblyInfotrue。这要求您删除 AssemblyInfo.cs 文件以防止这些属性重复。*

我通常解决这个问题的方法是在我的项目文件中定义我自己的一组与版本相关的属性(请参阅下面的 notes why).例如,您可能有以下内容:

<PropertyGroup>
   <GenerateAssemblyInfo>true</GenerateAssemblyInfo>
   <BaseVersion>31.1.13</BaseVersion>
   <InfoSuffix>v1.0.0</InfoSuffix>
</PropertyGroup>
<PropertyGroup>
   <!-- note: "-v1" is invalid in an Assembly Version; I assumed you meant this on the Informational one -->
   <InformationalVersion>$(BaseVersion)-$(InfoSuffix)</InformationalVersion>
   <AssemblyVersion>$(BaseVersion)</AssemblyVersion>
   <FileVersion>$(BaseVersion)</FileVersion>
</PropertyGroup>

如果您想显式覆盖它们,您可以在命令行上将这些属性中的任何一个传递给 MSBuild 或 dotnet build:

dotnet build -p:InfoSuffix=v2.0+1234
# alternatively, specify the MSBuild properties directly
dotnet build -p:FileVersion=1.2.3.4 -p:InformationalVersion=5.6.7.8

如果您有多个项目,您可以在一个 Directory.Build.props 文件中设置所有这些属性,以便它们一次应用于 所有 个项目。

一些笔记

首先,如果您正在使用 Directory.Build.props 机制和 运行 任何类型的 post 处理任务或诸如 SourceLink(将信息附加到信息版本)之类的东西,您将需要将第二个 属性 组移动到 Directory.Build.targets 文件中。如果您想将属性显式传递给其他工具,例如 dotnet pack.

,您也需要这样做

其次,MSBuild 具有一系列 other 版本相关的属性**。这些包括(但不限于):

  • SourceRevisionId - 附加到信息版(我们的 InfoSuffix
  • VersionPrefix - 基本版本
  • VersionSuffix - 设置预发布标签
  • PackageVersion - 生成 nuget 版本

您可以将这些与上面指定的结合使用。如果您想覆盖 project/props/targets 文件中的值,您甚至可以将它们作为属性传递给命令行。

现在您可能想知道为什么我费心定义自己的属性而不是使用内置属性。原因是 MSBuild 有一些奇怪的行为,有时 意外 行为取决于 这些属性的组合 的设置方式。有趣的是,我注意到不同的行为取决于我设置的值以及我是在 VS 中、在命令行上还是在使用 dotnet pack 中构建。正因为如此,我更喜欢定义自己的属性,然后使用它们来显式设置其他属性。它还允许我使用条件 MSBuild 逻辑来更轻松地设置版本的某些部分。虽然我承认,你的里程可能会有所不同。

* 如果要为 other 属性保留 AssemblyInfo.cs 文件,则必须通过利用单独的 GenerateX MSBuild properties 来禁用它们的自动生成.

** 有关其中一些属性的详细解释,请参阅 this blog post