简介
注意: 坑极多。而且截至2023年,这个东西仅仅是半成品
利用SourceGenerator可以在编译结束前生成一些代码参与编译,比如编译时反射之类的,还有模板代码生成都很好用。
使用
1. 创建项目
我们需要两个项目,创建完如下
- 类库项目(用作生成器)(注意只能是.NET Standard 2.0 ,别的无效)
- 控制台项目(用来测试)(至少是.NET 5.0或者以上,建议是6,7)
2.安装CodeAnalysis.Common包
注意:这个包是依赖Roslyn编译器的,所以请把VisualStudio更新到最新,这一点相当重要,或者你自行保证 编译器版本符合这个Nuget包的要求,如果不符合,在VS的警告里会发出提示。
严重性 说明 行
警告 分析器程序集“X:\Projects\ImportantProjects\SourceGenTest\SourceGen\bin\Debug\netstandard2.0\SourceGen.dll”引用了编译器的版本“4.6.0.0”,该版本高于当前正在运行的版本“4.4.0.0”。 1
3.写生成器
- 注意要实现ISourceGenerator接口
- 加上特性Generator (可以不写参数,也可以写"C#",或者我这么写也行)
- 尽量使用完全限定来防止名称冲突,global能进一步防止撞名字
- 使用"""三个引号能写格式化代码,很方便
- 记得打上特性标记代码由编译器生成,而非用户生成或者书写的,防止被滥用
using Microsoft.CodeAnalysis;
namespace SourceGen
{
[Generator(LanguageNames.CSharp)]
public sealed class HelloWorldGenerator : ISourceGenerator
{
void ISourceGenerator.Execute(GeneratorExecutionContext context)
{
const string version = "1.0";
context.AddSource("TestFile.cs",
$$"""
//<auto-generated/>
#nullable enable
namespace GenCode
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("{{nameof(HelloWorldGenerator)}}","{{version}}")]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
public static class GeneraredClass
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("{{nameof(HelloWorldGenerator)}}","{{version}}")]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]
public static void Hello()
{
global::System.Console.WriteLine("代码生成成功");
}
}
}
"""
);
}
//初始化,可以写一些筛选条件之类的
void ISourceGenerator.Initialize(GeneratorInitializationContext context)
{
}
}
}
写完就出警告了,在生成器项目需要添加Enforce…加上就OK了
4.引用生成器
引用完之后,在ItemGroup里只有Include,手动加上后两项。注意不要写错字母
注意本文内使用的C#版本较高,可能需要手动打开preview模式
生成器每次改动都需要重新生成这个项目!!!,建议第一次也重新生成
5.玄学施法时刻
重启VS
这样测试项目里就生成完毕了