编写源生成器
创建SampleGenerator.cs,添加[Generator]特性并实现IIncrementalGenerator接口
旧的源生成器ISourceGenerator在每次代码有更改时都会扫描整个语法树,开销很大。而新的增量生成器IIncrementalGenerator通过管道等方式遴选需要扫描的代码,大大减少生成开销。
因此这里我们选择IIncrementalGenerator进行实现
[Generator]
public class SampleGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
//在这里编写生成器逻辑
}
}
我们希望生成的代码如下,这里就放在一个常量中:
private const string HelloWorld =
"""
//加上此行以防止编译器进行不必要的代码分析,避免出现警告
//<auto-generated>
using System;
namespace SourceGeneratorDemo.Generator;
public class HelloWorld
{
public static void SayHello()
{
Console.WriteLine("Hello, World!");
}
}
""";
现在来编写Initialize方法,这是源生成器的核心部分:
public void Initialize(IncrementalGeneratorInitializationContext context)
{
//在编译时生成源代码
//HelloWorld.g.cs就是生成代码的文件名称
context.RegisterPostInitializationOutput(ctx => ctx.AddSource("HelloWorld.g.cs",SourceText.From(HelloWorld, Encoding.UTF8)));
}
所有代码如下:
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
namespace SourceGeneratorDemo.Generator;
[Generator]
public class SampleGenerator : IIncrementalGenerator
{
private const string HelloWorld =
"""
//加上此行以防止编译器进行不必要的代码分析,避免出现警告
//<auto-generated>
using System;
namespace SourceGeneratorDemo.Generator;
public class HelloWorld
{
public static void SayHello()
{
Console.WriteLine("Hello, World!");
}
}
""";
public void Initialize(IncrementalGeneratorInitializationContext context)
{
//在编译时生成源代码
context.RegisterPostInitializationOutput(ctx =>
ctx.AddSource("HelloWorld.g.cs",SourceText.From(HelloWorld, Encoding.UTF8)));
}
}