我正在尝试在此处的帖子之后向我的程序集添加自定义构建时间属性:https://blog.jermdavis.dev/posts/2023/build-metadata-dotnet
我为该属性添加了以下类文件:
using System;
using System.Globalization;
[AttributeUsage(AttributeTargets.Assembly)]
public class BuiltDateAttribute : Attribute {
public BuiltDateAttribute(string strTimestamp) {
this.Timestamp = DateTime.ParseExact(strTimestamp, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.None);
}
public DateTime Timestamp {
get; private set;
}
}
这是我用来读取程序集属性并将值添加到测试表单上的标签的代码:
BuiltDateAttribute oBuiltAt = Assembly.GetEntryAssembly().GetCustomAttribute<BuiltDateAttribute>();
if (oBuiltAt != null) {
lblBuiltAt.Text = string.Format("Built At: {0}", oBuiltAt.Timestamp);
}
else {
lblBuiltAt.Text = "! Built At Attribute Not Found !";
}
我已经更新了我的 .csproj 文件,将其作为最后一个块包含在内:
<ItemGroup>
<AssemblyAttribute Include="BuiltDateAttribute">
<_Parameter1>$([System.DateTime]::UtcNow.ToString("yyyyMMddHHmmss"))</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
当 Visual Studio 重新加载项目时,在解决方案资源管理器树视图中,它会以红色显示“BuildDateAttribute”作为丢失的文件。当我尝试从应用程序中检查它时,它也不会创建程序集属性。
构建解决方案不会在输出构建窗口中触发有关丢失文件的任何错误消息。它可以很好地构建和运行应用程序,只是不存在程序集属性。
我尝试在
.cs
文件和 Include
文件的 .csproj
中的类中添加命名空间。 VS 仅包含我在 .csproj
中指定的属性的命名空间作为缺失文件名的一部分。
我尝试从 Google 帖子中引用的基本系统命名空间添加属性 (
System.CLSCompliantAttribute
)。
在 Google 上搜索对其他人不起作用的程序集属性,似乎只会导致该功能在 2022 年的 VS for Mac 上不起作用,但此后已得到修复。 (https://developercommunity.visualstudio.com/t/Unable-to-hide-solution-tree-entry-and-m/10316409)
我的项目是使用 Framework 4.8 的 C#,从文档中可以看出,应该支持它,因为它是 MSBuild 功能。我使用的是最新版本的 Visual Studio 2022 (17.9.6) 并且“检查更新”表示我对所有内容都是最新的。
显然正如 @jonathan-dodds 所说,我使用的是旧版 VS 项目类型而不是 SDK 项目类型。我在下面的 MS 开发者社区上发布了我收到的答案和潜在的解决方法(如果不切换项目类型)。
https://developercommunity.visualstudio.com/t/Visual-Studio-2022---CSPROJ-AssemblyAttr/10649290
https://blog.jermdavis.dev/posts/2023/build-metadata-dotnet中描述的方法仅适用于 SDK 样式的 .NET 项目。在您的项目中,MSBuild 知道您声明了一个名为“BuiltDateAttribute”的“AssemblyAttribute”项,但不理解这意味着什么,这就是为什么它以解决方案资源管理器中的方式显示的原因 - 它假设它必须是一个文件,但不存在该名称的文件。
您仍然可以通过在项目中添加类似的内容来实现您想要的目标:
<Target Name="CreateMyAssemblyInfo" BeforeTargets="Compile">
<ItemGroup>
<AssemblyAttributes Include="BuiltAtAttribute">
<_Parameter1>$([System.DateTime]::UtcNow.ToString("yyyyMMddHHmmss"))</_Parameter1>
</AssemblyAttributes>
</ItemGroup>
<WriteCodeFragment Language="C#" OutputFile="Properties\MyAssemblyInfo.cs" AssemblyAttributes="@(AssemblyAttributes)" />
</Target>
<ItemGroup>
<Compile Name="Properties\MyAssemblyInfo.cs" />
</ItemGroup>
此 MSBuild Target
将在标准
Compile
目标运行之前运行,并使用程序集属性在“Properties\MyAssemblyInfo.cs”中创建一个文件。然后,
Compile
项会将该文件作为编译的一部分包含在内。但是,我强烈建议反对这种方法。通过这样做,您将使您的构建依赖于不断变化的输入:当前时间。 MSBuild 尽力避免重新运行输入未更改的构建部分;取决于日期/时间,这种方式意味着它总是必须重新运行昂贵的构建步骤。 Visual Studio 还运行有限形式的构建来收集 Intellisense 和其他编辑器功能所需的信息,因此还需要运行更多此类构建。
如果您确实需要这样做,我建议仅在 CI 或最终发布版本中打开此功能,并始终在开发人员版本中使用硬编码值作为日期/时间。
希望这有帮助, -汤姆·梅施特