1. .NET源码生成器开发概述
在.NET生态系统中,源码生成器(Source Generators)是一项强大的编译时元编程能力。它允许开发者在编译阶段动态生成C#代码,这些生成的代码会与手写代码一起参与编译。基于partial类型的开发范式,我们可以实现干净优雅的代码生成方案。
partial类型是C# 2.0引入的特性,它允许我们将一个类的定义分散在多个文件中。源码生成器正是利用这一特性,将生成的代码作为partial类的一部分,与开发者手写的代码合并编译。这种方式相比传统的T4模板或运行时反射,具有以下优势:
- 编译时完成:生成的代码直接参与编译,没有运行时开销
- 类型安全:生成的代码与手写代码一样经过编译器检查
- 开发体验:Visual Studio能实时显示生成的代码,提供智能感知
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 源码生成器核心实现
2.1 项目结构与依赖配置
创建一个源码生成器项目需要遵循特定的项目结构。我们首先创建一个.NET Standard 2.0类库项目:
bash复制dotnet new classlib -n MySourceGenerator -f netstandard2.0
然后修改项目文件,添加必要的NuGet包引用和生成器配置:
xml复制<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" PrivateAssets="all" />
</ItemGroup>
</Project>
关键配置说明:
EnforceExtendedAnalyzerRules:启用完整的分析器规则IsRoslynComponent:标记这是一个Roslyn组件PrivateAssets="all":确保这些依赖不会传递到使用生成器的项目
2.2 实现ISourceGenerator接口
源码生成器的核心是实现ISourceGenerator接口。我们创建一个新的类:
csharp复制[Generator]
public class MySourceGenerator : ISourceGenerator
{
public void Initialize(GeneratorInitializationContext context)
{
// 注册语法接收器,用于收集编译信息
context.RegisterForSyntaxNotifications(() => new MySyntaxReceiver());
}
public void Execute(GeneratorExecutionContext context)
{
// 获取语法接收器收集的信息
if (context.SyntaxReceiver is not MySyntaxReceiver receiver)
return;
// 生成源代码的逻辑
var sourceCode = GenerateSource(receiver);
// 将生成的代码添加到编译上下文
context.AddSource("GeneratedCode.cs", SourceText.From(sourceCode, Encoding.UTF8));
}
private string GenerateSource(MySyntaxReceiver receiver)
{
// 实际的代码生成逻辑
// ...
}
}
2.3 语法接收器实现
语法接收器用于在编译过程中收集我们需要的信息:
csharp复制class MySyntaxReceiver : ISyntaxReceiver
{
public List<ClassDeclarationSyntax> CandidateClasses { get; } = new();
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
// 识别带有特定特性的类
if (syntaxNode is ClassDeclarationSyntax classDecl &&
classDecl.AttributeLists.Count > 0)
{
CandidateClasses.Add(classDecl);
}
}
}
3. 基于partial范式的代码生成
3.1 设计生成策略
使用partial范式时,我们通
