T2FGame.CodeGen 1.0.5

There is a newer version of this package available.
See the version list below for details.
dotnet add package T2FGame.CodeGen --version 1.0.5
                    
NuGet\Install-Package T2FGame.CodeGen -Version 1.0.5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="T2FGame.CodeGen" Version="1.0.5">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="T2FGame.CodeGen" Version="1.0.5" />
                    
Directory.Packages.props
<PackageReference Include="T2FGame.CodeGen">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add T2FGame.CodeGen --version 1.0.5
                    
#r "nuget: T2FGame.CodeGen, 1.0.5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package T2FGame.CodeGen@1.0.5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=T2FGame.CodeGen&version=1.0.5
                    
Install as a Cake Addin
#tool nuget:?package=T2FGame.CodeGen&version=1.0.5
                    
Install as a Cake Tool

T2FGame.CodeGen

T2FGame 代码生成基础框架,提供 Source Generator 开发所需的通用工具和抽象。

为什么使用 netstandard2.0?

这是 Source Generator 的强制要求,不是可选项。

技术原因

┌─────────────────────────────────────────────────────────────────┐
│                    编译时环境 (Compile Time)                      │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Visual Studio / dotnet build / Rider                          │
│         │                                                       │
│         ▼                                                       │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │                    Roslyn Compiler                       │   │
│   │   运行在 .NET Framework 4.7.2 或 netstandard2.0 兼容环境   │   │
│   └─────────────────────────────────────────────────────────┘   │
│         │                                                       │
│         ▼  加载                                                  │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │            Source Generator DLL                          │   │
│   │            必须是 netstandard2.0                          │   │
│   └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
原因 说明
Visual Studio 限制 VS 内置的 Roslyn 编译器运行在 .NET Framework 进程中
MSBuild 兼容性 MSBuild 可能运行在 .NET Framework 或 .NET Core
IDE 实时分析 代码编辑时的实时生成需要在 IDE 进程中运行
跨平台 IDE Rider、VS Code 等 IDE 的 Roslyn 实现也依赖 netstandard2.0

如果使用更高版本会怎样?


<TargetFramework>net9.0</TargetFramework>

结果

  • Visual Studio 无法加载生成器 → 编译错误
  • dotnet build 在某些环境下失败
  • IDE 智能提示失效

但这不意味着功能受限

代码类型 限制 说明
生成器代码 netstandard2.0 生成器本身的代码受限
生成的代码 (.g.cs) 无限制 可使用目标框架的所有特性

生成器可以使用 C# 12 语法(通过 LangVersion)和 PolySharp polyfill, 同时生成使用 .NET 9 特性的代码(如 FrozenDictionary)。

项目结构

T2FGame.CodeGen/
├── Abstractions/           # 核心抽象
│   ├── GeneratorContext.cs # 生成上下文
│   ├── GeneratedSource.cs  # 生成的源文件
│   ├── ICodeGenerator.cs   # 生成器接口
│   ├── ICodeEmitter.cs     # 发射器接口
│   └── ISymbolAnalyzer.cs  # 符号分析器接口
│
├── Builders/               # 代码构建器
│   ├── CodeBuilder.cs      # 通用代码构建器
│   ├── ClassBuilder.cs     # 类构建器
│   └── SwitchExpressionBuilder.cs # Switch 表达式构建器
│
├── Templates/              # 模板系统
│   ├── ICodeTemplate.cs    # 模板接口
│   ├── FileHeaderTemplate.cs   # 文件头模板
│   └── NamespaceTemplate.cs    # 命名空间模板
│
├── Analyzers/              # Roslyn 分析工具
│   ├── TypeAnalyzer.cs     # 类型分析
│   ├── AttributeAnalyzer.cs # 特性分析
│   ├── MethodAnalyzer.cs   # 方法分析
│   └── ProtobufAnalyzer.cs # Protobuf 分析
│
├── Models/                 # 共享模型
│   ├── EquatableArray.cs   # 可比较数组(增量生成器缓存)
│   └── TypeModel.cs        # 类型模型
│
└── Extensions/             # 扩展方法
    ├── SymbolExtensions.cs # ISymbol 扩展
    └── StringExtensions.cs # 字符串工具

使用示例

创建代码构建器

var builder = new CodeBuilder();

// 文件头
builder.AppendLines(FileHeaderTemplate.Instance.Render(new FileHeaderModel
{
    GeneratorName = "MyGenerator",
    GeneratorVersion = "1.0.0",
    Usings = new[] { "System", "System.Collections.Generic" }
}));

// 命名空间和类
using (builder.Namespace("MyNamespace"))
{
    builder.Summary("自动生成的类");
    builder.GeneratedCodeAttribute("MyGenerator", "1.0.0");

    using (builder.Class("public sealed", "GeneratedClass"))
    {
        // 字段
        builder.AppendLine("private readonly int _value;");

        // 方法
        using (builder.Method("public int GetValue()"))
        {
            builder.AppendLine("return _value;");
        }
    }
}

string code = builder.ToString();

使用 ClassBuilder 流式 API

var classBuilder = new ClassBuilder("MyClass")
    .Sealed()
    .Implements("IMyInterface")
    .GeneratedCodeAttribute("MyGenerator", "1.0.0")
    .Field("int", "_count", accessibility: "private", isReadonly: true)
    .Property("int", "Count", hasGetter: true, hasSetter: false)
    .Method("public void Increment()", b =>
    {
        b.AppendLine("_count++;");
    });

classBuilder.Build(builder);

分析 Roslyn 符号

// 分析返回类型
var asyncInfo = TypeAnalyzer.AnalyzeAsyncType(methodSymbol.ReturnType);
if (asyncInfo.Kind == AsyncKind.TaskOfT)
{
    var resultType = asyncInfo.ResultType;
    // 处理 Task<T> 返回类型
}

// 获取特性参数
var attr = AttributeAnalyzer.GetAttribute(symbol, "MyAttribute");
var value = AttributeAnalyzer.GetConstructorArgument<int>(attr, 0);

// 检查 Protobuf 消息
if (ProtobufAnalyzer.IsProtobufMessage(type))
{
    var parserExpr = ProtobufAnalyzer.GetParserExpression(type);
}

扩展生成器

创建新的 Source Generator 项目时:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <LangVersion>12.0</LangVersion>
    <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
    <IsRoslynComponent>true</IsRoslynComponent>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
    <ProjectReference Include="..\T2FGame.CodeGen\T2FGame.CodeGen.csproj" PrivateAssets="all" />
  </ItemGroup>
</Project>

许可证

MIT License

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.9 417 12/11/2025
1.0.8 418 12/11/2025
1.0.7 407 12/11/2025
1.0.6 422 12/11/2025
1.0.5 432 12/10/2025
1.0.4 436 12/10/2025
1.0.3 440 12/9/2025
1.0.2 338 12/8/2025
0.0.1 348 12/8/2025