【问题标题】:Set Attribute Value at Compile Time在编译时设置属性值
【发布时间】:2019-01-28 00:05:24
【问题描述】:

我有一个使用 System.AddIn 程序集属性的程序集:

[AddIn("Foobar", Version = "1.2.3.4")]
public class Foobar {
...

我通常在项目属性的 Assembly Information 中维护版本信息 - 在 Assembly versionFile version 字段中。

是否有任何魔术常量或编译时常量可用于使属性版本与我的程序集或文件版本保持同步?

这看起来像是一个可能的后备选项,如果不是: Is it possible to get assembly info at compile time without reflection?

【问题讨论】:

  • 为什么你需要它而不需要反思?
  • 理想情况下,它只在编译时设置。而且我尽量不要弄乱私有字段(属性值是公开只读的)。

标签: c# compile-time-constant


【解决方案1】:

好的,这是一个复杂的解决方法。

将您的课程更改为部分课程。将所有逻辑放在一个主文件中。在一个单独的文件中,用你想要的属性装饰你的类。见Can I define properties in partial classes, then mark them with attributes in another partial class?

除了,将第二个类设为 T4 模板。

类似于以下内容:

Foobar.cs

public partial class Foobar {
    // regular code
    ...
}

FoobarAttributes.tt(这里的语法高亮是错误的)

<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#
int major = 1;
int minor = 0;
int revision = 1;
int build = 1;

    try
    {
        // Code here is copied from a template in the Properties 
        // folder that auto-increments the build version, so that's the file location  
        string currentDirectory = Path.GetDirectoryName(Host.TemplateFile);
        string assemblyInfo = File.ReadAllText(Path.Combine(currentDirectory,"AssemblyInfo.cs"));
        Regex pattern = new Regex("AssemblyVersion\\(\"\\d+\\.\\d+\\.(?<revision>\\d+)\\.(?<build>\\d+)\"\\)");
        MatchCollection matches = pattern.Matches(assemblyInfo);
        revision = Convert.ToInt32(matches[0].Groups["revision"].Value);
        build = Convert.ToInt32(matches[0].Groups["build"].Value) + (incBuild?1:0);
    }
    catch(Exception)
    { }
#>
[AddIn("Foobar", Version = "<#= this.major #>.<#= this.minor #>.<#= this.revision #>.<#= this.build #>")]
public partial class Foobar
{
    // ...
}

设置一个事件以在构建时编译模板。现在您可以将 C# 代码写入 T4 以从其他文件中提取/修改文本,从而为您的属性提供正确的版本信息(参见上面的一些示例代码)。

我找不到我(前段时间)从中提取的 SO 答案,但我正在从构建事件中运行转换

"%CommonProgramFiles(x86)%\microsoft shared\TextTemplating\$(VisualStudioVersion)\TextTransform.exe" -a !!build!true "$(ProjectDir)Properties\AssemblyInfo.tt"

但请参阅Get Visual Studio to run a T4 Template on every build 了解一些类似的想法。

我不确定这是不是正确的解决方案,总的来说,我建议不要使用 T4,因为它增加了复杂性,但你去吧。

编辑:上面链接的部分类帖子适用于属性,您应该能够添加属性而无需为部分类创建元数据类。

【讨论】:

  • 所以我同意你的看法,模板方法有点复杂,但它确实可以满足我的要求,尽管它并不是某种简单的编译时常量。也就是说,为了简单起见,我可能会使用回退方法。不过,感谢您的创新方法!将此标记为答案,以防将来备用选项对其他人不起作用。
猜你喜欢
  • 2015-08-15
  • 2019-04-29
  • 2018-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 2020-06-12
相关资源
最近更新 更多