你听说过布吗?它有一些有趣的方法可以让您连接到编译器管道。其中一项功能称为语法属性,它是实现编译器调用的接口的属性,以便它们可以参与代码生成。
class Person:
[getter(FirstName)]
_fname as string
[getter(LastName)]
_lname as string
def constructor([required] fname, [required] lname):
_fname = fname
_lname = lname
此代码中的属性将为字段生成公共 getter,并为构造函数参数生成 null 检查。它将全部出现在已编译的程序集中。
我一直希望这种可扩展性成为 C# 编译器的一部分。也许有一天会。在此之前,您可以使用后编译器,例如CciSharp。CCiSharp 将根据程序集中的特殊属性重写CIL,就像使用 Boo 同步属性一样。
鉴于此代码:
class Foo {
[Lazy]
public int Value {
get { return Environment.Ticks; }
}
}
CCiSharp 将根据以下内容对代码进行变异LazyAttribute
:
class Foo {
int Value$Value; // compiler generated
int Value$Initialized;
int GetValueUncached() {
return Environment.Ticks;
}
public int Value {
get {
if(!this.Value$Initialized) {
this.Value$Value = this.GetValueUncached();
this.Value$Initialized = true;
}
return this.Value$Value;
}
}
CCiSharp 基于Common Compiler Infrastructure项目,用于在即将推出的 .NET Framework 4.0 中实现代码协定后编译器。
所以这就是你可以改变生成的 CIL 的方法。
但是,#warning
指令没有 CIL 表示,它只是一个编译器指令。要添加此指令,您必须改变的不是生成的 CIL,而是 C# 代码本身。您必须为此实现一个 C# 解析器。正如其他回复中所述,我认为最好的选择是创建一个构建后事件,该事件将反映生成的程序集并发出所需的警告。