Hand.GenerateConvert
0.2.1-alpha
This is a prerelease version of Hand.GenerateConvert.
dotnet add package Hand.GenerateConvert --version 0.2.1-alpha
NuGet\Install-Package Hand.GenerateConvert -Version 0.2.1-alpha
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="Hand.GenerateConvert" Version="0.2.1-alpha" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Hand.GenerateConvert" Version="0.2.1-alpha" />
<PackageReference Include="Hand.GenerateConvert" />
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 Hand.GenerateConvert --version 0.2.1-alpha
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Hand.GenerateConvert, 0.2.1-alpha"
#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 Hand.GenerateConvert@0.2.1-alpha
#: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=Hand.GenerateConvert&version=0.2.1-alpha&prerelease
#tool nuget:?package=Hand.GenerateConvert&version=0.2.1-alpha&prerelease
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
SourceGenerator之partial范式
- 封装SourceGenerator常用功能
- partial范式的最佳实践
一、什么是partial范式
- partial关键字允许将一个类或方法分散到多个文件中
- 所以partial是代码生成的一个很好的抓手
- 再配合Attribute特性,可以更准确定位需要生成代码的类或方法
- 对代码按规则自动补足,减少重复代码编写及其可能导致的失误
- 笔者称之为SourceGenerator的partial范式
- 开源项目Hand.GenerateCore用于践行partial范式
二、partial范式的要素
1. 标记定位
- 通过Attribute特性来标记需要代码补足的位置
- Attribute的命名最好与调用的SourceGenerator一致
- 需要生成的类有相应的Attribute也可以增加可读性(有预期该类包含自动生成的代码)
- partial范式通过官方方法SyntaxValueProvider.ForAttributeWithMetadataName来标记定位
2. 节点过滤
- ISyntaxFilter是节点过滤接口
- SyntaxFilter是默认实现,实现按节点类型和是否为partial来过滤
interface ISyntaxFilter
{
bool Match(SyntaxNode node, CancellationToken cancellation = default);
}
class SyntaxFilter(bool isPartial, params SyntaxKind[] kinds)
: ISyntaxFilter
3. 转化源对象
- IGeneratorSource是转化源接口
- GenerateFileName是生成文件名属性
- Generate是生成代码方法
public interface IGeneratorSource
{
string GenerateFileName { get; }
SyntaxGenerator Generate();
}
4. 转化过滤
- 对节点预处理
- 如果不满足生成必要条件返回null会被自动过滤
- ISyntaxTransform是转化接口
- PassTransform是默认实现,直接返回官方对象
- TSource一般实现接口IGeneratorSource
interface IGeneratorTransform<TSource>
{
TSource? Transform(GeneratorAttributeSyntaxContext context, CancellationToken cancellation);
}
class PassTransform : IGeneratorTransform<GeneratorAttributeSyntaxContext>
{
public GeneratorAttributeSyntaxContext Transform(GeneratorAttributeSyntaxContext context, CancellationToken cancellation)
=> context;
}
5. 执行生成
- IGeneratorExecutor是执行接口
- GeneratorExecutor是默认实现,一般可以执行使用
interface IGeneratorExecutor<TSource>
{
void Execute(SourceProductionContext context, TSource source);
}
class GeneratorExecutor<TSource> : IGeneratorExecutor<TSource>
where TSource : IGeneratorSource
{
public virtual void Execute(SourceProductionContext context, TSource source)
{
var cancellation = context.CancellationToken;
if (cancellation.IsCancellationRequested)
return;
var builder = source.Generate();
var code = builder.Build()
.WithGenerated()
.ToFullString();
context.AddSource(source.GenerateFileName, code);
}
}
6. 生成器基类ValuesGenerator
- 通过ValuesGenerator简化代码生成器开发
- 把业务逻辑都提取到TSource中
- filter、transform和executor都会很简单
class ValuesGenerator<TSource>(
string attributeName,
ISyntaxFilter filter,
ISyntaxTransform<TSource> transform,
ISyntaxExecutor<TSource> executor);
三、通过ValuesGenerator实现代码生成器的Case
- 定义类型HelloGenerator继承ValuesGenerator即可
- 另外需要实现HelloGeneratorAttribute、HelloTransform和HelloSource
1. HelloGenerator代码非常简单
- 含义是查找HelloGenerator标记
- 查找含partial修饰的类
- 转化为HelloSource
- 用HelloSource生成代码
public class HelloGenerator()
: ValuesGenerator<HelloSource>(
"GenerateCoreTests.Hello.HelloGeneratorAttribute",
new SyntaxFilter(true, SyntaxKind.ClassDeclaration),
new HelloTransform(),
new GeneratorExecutor<HelloSource>())
{
}
2. HelloGeneratorAttribute非常简单
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class HelloGeneratorAttribute : Attribute
{
}
3. HelloTransform非常简单
public class HelloTransform : IGeneratorTransform<HelloSource>
{
public HelloSource? Transform(GeneratorAttributeSyntaxContext context, CancellationToken cancellation)
{
if (context.TargetNode is ClassDeclarationSyntax type && context.TargetSymbol is INamedTypeSymbol symbol)
return new(type, symbol);
return null;
}
}
4. HelloSource是比较纯净的业务逻辑
public class HelloSource(ClassDeclarationSyntax type, INamedTypeSymbol symbol)
: IGeneratorSource
{
private readonly ClassDeclarationSyntax _type = type;
private readonly INamedTypeSymbol _symbol = symbol;
public string GenerateFileName
=> $"{_symbol.ToDisplayString()}.Hello.g.cs";
public SyntaxGenerator Generate()
{
var builder = SyntaxGenerator.Clone(_type);
var method = GenerateMethod();
builder.AddMember(method);
return builder;
}
public static MethodDeclarationSyntax GenerateMethod()
{
var name = SyntaxFactory.IdentifierName("name");
var expression = SyntaxGenerator.Interpolation()
.Add("Hello: '")
.Add(name)
.Add("'")
.Build();
return SyntaxGenerator.VoidType.Method("SayHello", SyntaxGenerator.StringType.Parameter(name.Identifier))
.Public()
.Static()
.ToBuilder()
.Add(SyntaxFactory.IdentifierName("Console").Access("WriteLine").Invocation([expression]))
.End();
}
}
5. 测试代码如下
namespace GenerateCoreTests.Hello;
[HelloGenerator]
public partial class HelloTests;
6. 生成代码如下
// <auto-generated/>
namespace GenerateCoreTests.Hello;
partial class HelloTests
{
public static void SayHello(string name)
{
Console.WriteLine($"Hello: '{name}'");
}
}
There are no supported framework assets in this package.
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- Hand.AutoCache (>= 0.3.1.2-alpha)
- Hand.GenerateCore (>= 0.2.1.1)
- Hand.Generators.Attributes (>= 0.2.1.3)
- Hand.Generators.EasySyntax (>= 0.2.1.1)
- Hand.MemberValidation (>= 0.3.1.2-alpha)
- Hand.Naming (>= 0.3.1.1-alpha)
- Hand.ParseXml (>= 0.3.1.3-alpha)
- Hand.Projections (>= 0.3.1.5-alpha)
- Microsoft.Bcl.HashCode (>= 6.0.0)
- Microsoft.CodeAnalysis.Analyzers (>= 5.6.0)
- Microsoft.CodeAnalysis.CSharp (>= 5.6.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Hand.GenerateConvert:
| Package | Downloads |
|---|---|
|
Hand.GeneratePoco
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.2.1-alpha | 0 | 8/2/2026 |