代码生成 API 高级指南
🎯 学习目标
完成本指南后,你将能够:
- [ ] 使用 SyntaxFactory 生成复杂的代码结构
- [ ] 实现高级构建器模式和代码转换技术
- [ ] 掌握性能优化策略
- [ ] 处理边缘情况和特殊场景
- [ ] 实现代码重构和转换工具
📖 核心概念
复杂代码生成的挑战
在高级场景中,代码生成面临以下挑战:
- 结构复杂性 - 需要生成嵌套的、相互关联的代码结构
- 性能要求 - 大规模代码生成需要优化性能
- 可维护性 - 生成的代码需要易于理解和维护
- 类型安全 - 确保生成的代码在编译时类型安全
高级技术概览
- 语法树转换 - 修改现有代码而不是从头生成
- 模板引擎集成 - 结合模板引擎提高灵活性
- 增量生成 - 只生成变化的部分
- 代码分析驱动 - 基于语义分析生成代码
🔧 复杂结构生成
生成泛型类和约束
csharp
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
/// <summary>
/// 生成复杂的泛型类
/// </summary>
public class AdvancedGenericClassGeneration
{
/// <summary>
/// 生成带多个约束的泛型类
/// public class Repository<TEntity, TKey>
/// where TEntity : class, IEntity<TKey>, new()
/// where TKey : struct
/// </summary>
public ClassDeclarationSyntax GenerateRepositoryClass()
{
return ClassDeclaration("Repository")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddTypeParameterListParameters(
TypeParameter("TEntity"),
TypeParameter("TKey"))
.AddConstraintClauses(
// where TEntity : class, IEntity<TKey>, new()
TypeParameterConstraintClause("TEntity")
.AddConstraints(
ClassOrStructConstraint(SyntaxKind.ClassConstraint),
TypeConstraint(
GenericName("IEntity")
.AddTypeArgumentListArguments(IdentifierName("TKey"))),
ConstructorConstraint()),
// where TKey : struct
TypeParameterConstraintClause("TKey")
.AddConstraints(
ClassOrStructConstraint(SyntaxKind.StructConstraint)));
}
}生成嵌套类和内部类型
csharp
/// <summary>
/// 生成嵌套类结构
/// </summary>
public class NestedClassGeneration
{
/// <summary>
/// 生成包含嵌套类的外部类
/// public class Outer
/// {
/// public class Inner
/// {
/// public string Value { get; set; }
/// }
/// }
/// </summary>
public ClassDeclarationSyntax GenerateNestedClass()
{
// 创建内部类
var innerClass = ClassDeclaration("Inner")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddMembers(
PropertyDeclaration(
PredefinedType(Token(SyntaxKind.StringKeyword)),
"Value")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken))));
// 创建外部类并添加内部类
return ClassDeclaration("Outer")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddMembers(innerClass);
}
}生成复杂的方法体
csharp
/// <summary>
/// 生成包含复杂逻辑的方法
/// </summary>
public class ComplexMethodGeneration
{
/// <summary>
/// 生成包含 try-catch、循环和条件的方法
/// public async Task<List<T>> ProcessItemsAsync<T>(IEnumerable<T> items)
/// {
/// var results = new List<T>();
/// try
/// {
/// foreach (var item in items)
/// {
/// if (item != null)
/// {
/// await ProcessAsync(item);
/// results.Add(item);
/// }
/// }
/// }
/// catch (Exception ex)
/// {
/// Logger.LogError(ex);
/// throw;
/// }
/// return results;
/// }
/// </summary>
public MethodDeclarationSyntax GenerateComplexMethod()
{
// 创建方法签名
var method = MethodDeclaration(
GenericName("Task")
.AddTypeArgumentListArguments(
GenericName("List")
.AddTypeArgumentListArguments(IdentifierName("T"))),
"ProcessItemsAsync")
.AddModifiers(
Token(SyntaxKind.PublicKeyword),
Token(SyntaxKind.AsyncKeyword))
.AddTypeParameterListParameters(TypeParameter("T"))
.AddParameterListParameters(
Parameter(Identifier("items"))
.WithType(
GenericName("IEnumerable")
.AddTypeArgumentListArguments(IdentifierName("T"))));
// 创建方法体
var methodBody = Block(
// var results = new List<T>();
LocalDeclarationStatement(
VariableDeclaration(IdentifierName("var"))
.AddVariables(
VariableDeclarator("results")
.WithInitializer(
EqualsValueClause(
ObjectCreationExpression(
GenericName("List")
.AddTypeArgumentListArguments(IdentifierName("T")))
.WithArgumentList(ArgumentList()))))),
// try-catch 块
TryStatement(
Block(
// foreach (var item in items)
ForEachStatement(
IdentifierName("var"),
"item",
IdentifierName("items"),
Block(
// if (item != null)
IfStatement(
BinaryExpression(
SyntaxKind.NotEqualsExpression,
IdentifierName("item"),
LiteralExpression(SyntaxKind.NullLiteralExpression)),
Block(
// await ProcessAsync(item);
ExpressionStatement(
AwaitExpression(
InvocationExpression(
IdentifierName("ProcessAsync"))
.AddArgumentListArguments(
Argument(IdentifierName("item"))))),
// results.Add(item);
ExpressionStatement(
InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName("results"),
IdentifierName("Add")))
.AddArgumentListArguments(
Argument(IdentifierName("item"))))))))),
// catch (Exception ex)
SingletonList(
CatchClause()
.WithDeclaration(
CatchDeclaration(IdentifierName("Exception"))
.WithIdentifier(Identifier("ex")))
.WithBlock(
Block(
// Logger.LogError(ex);
ExpressionStatement(
InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName("Logger"),
IdentifierName("LogError")))
.AddArgumentListArguments(
Argument(IdentifierName("ex")))),
// throw;
ThrowStatement()))),
null,
null),
// return results;
ReturnStatement(IdentifierName("results")));
return method.WithBody(methodBody);
}
}🏗️ 高级构建器模式
流式构建器实现
csharp
/// <summary>
/// 高级流式构建器,支持链式调用和条件构建
/// </summary>
public class FluentClassBuilder
{
private string _className;
private List<SyntaxToken> _modifiers = new();
private List<MemberDeclarationSyntax> _members = new();
private List<TypeParameterSyntax> _typeParameters = new();
private List<TypeParameterConstraintClauseSyntax> _constraints = new();
private List<BaseTypeSyntax> _baseTypes = new();
private List<AttributeListSyntax> _attributes = new();
public FluentClassBuilder(string className)
{
_className = className;
}
/// <summary>
/// 添加修饰符
/// </summary>
public FluentClassBuilder WithModifier(SyntaxKind modifier)
{
_modifiers.Add(Token(modifier));
return this;
}
/// <summary>
/// 添加泛型参数
/// </summary>
public FluentClassBuilder WithTypeParameter(
string name,
params TypeParameterConstraintSyntax[] constraints)
{
_typeParameters.Add(TypeParameter(name));
if (constraints.Any())
{
_constraints.Add(
TypeParameterConstraintClause(name)
.AddConstraints(constraints));
}
return this;
}
/// <summary>
/// 添加基类或接口
/// </summary>
public FluentClassBuilder WithBaseType(string typeName)
{
_baseTypes.Add(SimpleBaseType(IdentifierName(typeName)));
return this;
}
/// <summary>
/// 添加特性
/// </summary>
public FluentClassBuilder WithAttribute(string attributeName, params string[] arguments)
{
var attribute = Attribute(IdentifierName(attributeName));
if (arguments.Any())
{
attribute = attribute.AddArgumentListArguments(
arguments.Select(arg =>
AttributeArgument(
LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal(arg))))
.ToArray());
}
_attributes.Add(AttributeList(SingletonSeparatedList(attribute)));
return this;
}
/// <summary>
/// 添加成员
/// </summary>
public FluentClassBuilder WithMember(MemberDeclarationSyntax member)
{
_members.Add(member);
return this;
}
/// <summary>
/// 条件添加成员
/// </summary>
public FluentClassBuilder WithMemberIf(
bool condition,
Func<MemberDeclarationSyntax> memberFactory)
{
if (condition)
{
_members.Add(memberFactory());
}
return this;
}
/// <summary>
/// 批量添加成员
/// </summary>
public FluentClassBuilder WithMembers(IEnumerable<MemberDeclarationSyntax> members)
{
_members.AddRange(members);
return this;
}
/// <summary>
/// 构建类声明
/// </summary>
public ClassDeclarationSyntax Build()
{
var classDecl = ClassDeclaration(_className);
// 添加特性
if (_attributes.Any())
{
classDecl = classDecl.AddAttributeLists(_attributes.ToArray());
}
// 添加修饰符
if (_modifiers.Any())
{
classDecl = classDecl.AddModifiers(_modifiers.ToArray());
}
// 添加泛型参数
if (_typeParameters.Any())
{
classDecl = classDecl.WithTypeParameterList(
TypeParameterList(SeparatedList(_typeParameters)));
}
// 添加基类和接口
if (_baseTypes.Any())
{
classDecl = classDecl.WithBaseList(
BaseList(SeparatedList(_baseTypes)));
}
// 添加约束
if (_constraints.Any())
{
classDecl = classDecl.AddConstraintClauses(_constraints.ToArray());
}
// 添加成员
if (_members.Any())
{
classDecl = classDecl.AddMembers(_members.ToArray());
}
return classDecl;
}
}使用示例
csharp
/// <summary>
/// 使用流式构建器的示例
/// </summary>
public class FluentBuilderUsageExample
{
public ClassDeclarationSyntax GenerateRepositoryClass()
{
return new FluentClassBuilder("Repository")
.WithModifier(SyntaxKind.PublicKeyword)
.WithTypeParameter("TEntity",
ClassOrStructConstraint(SyntaxKind.ClassConstraint))
.WithBaseType("IRepository<TEntity>")
.WithAttribute("GeneratedCode", "MyGenerator", "1.0")
.WithMember(CreateSaveMethod())
.WithMember(CreateLoadMethod())
.WithMemberIf(includeDeleteMethod, () => CreateDeleteMethod())
.Build();
}
private bool includeDeleteMethod = true;
private MethodDeclarationSyntax CreateSaveMethod() { /* ... */ return null; }
private MethodDeclarationSyntax CreateLoadMethod() { /* ... */ return null; }
private MethodDeclarationSyntax CreateDeleteMethod() { /* ... */ return null; }
}🔄 代码转换技术
语法树重写器
csharp
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
/// <summary>
/// 自定义语法重写器,用于转换现有代码
/// </summary>
public class PropertyToFieldRewriter : CSharpSyntaxRewriter
{
/// <summary>
/// 将自动属性转换为字段
/// </summary>
public override SyntaxNode VisitPropertyDeclaration(
PropertyDeclarationSyntax node)
{
// 只处理自动属性
if (!IsAutoProperty(node))
{
return base.VisitPropertyDeclaration(node);
}
// 创建字段名 (Name -> _name)
var fieldName = $"_{char.ToLower(node.Identifier.Text[0])}" +
node.Identifier.Text.Substring(1);
// 创建字段声明
var field = FieldDeclaration(
VariableDeclaration(node.Type)
.AddVariables(VariableDeclarator(fieldName)))
.WithModifiers(TokenList(Token(SyntaxKind.PrivateKeyword)));
// 保留原属性的前导和尾随 trivia
field = field.WithLeadingTrivia(node.GetLeadingTrivia())
.WithTrailingTrivia(node.GetTrailingTrivia());
return field;
}
private bool IsAutoProperty(PropertyDeclarationSyntax property)
{
return property.AccessorList?.Accessors
.All(a => a.Body == null && a.ExpressionBody == null) ?? false;
}
}使用语法重写器
csharp
/// <summary>
/// 使用语法重写器转换代码
/// </summary>
public class CodeTransformationExample
{
public string TransformPropertiesToFields(string sourceCode)
{
// 解析源代码
var tree = CSharpSyntaxTree.ParseText(sourceCode);
var root = tree.GetRoot();
// 应用重写器
var rewriter = new PropertyToFieldRewriter();
var newRoot = rewriter.Visit(root);
// 格式化并返回
return newRoot.NormalizeWhitespace().ToFullString();
}
}批量代码转换
csharp
/// <summary>
/// 批量转换多个文件
/// </summary>
public class BatchCodeTransformer
{
/// <summary>
/// 转换项目中的所有文件
/// </summary>
public async Task TransformProjectAsync(
string projectPath,
CSharpSyntaxRewriter rewriter)
{
var workspace = MSBuildWorkspace.Create();
var project = await workspace.OpenProjectAsync(projectPath);
foreach (var document in project.Documents)
{
var tree = await document.GetSyntaxTreeAsync();
var root = await tree.GetRootAsync();
// 应用转换
var newRoot = rewriter.Visit(root);
// 如果有变化,更新文档
if (newRoot != root)
{
var newDocument = document.WithSyntaxRoot(newRoot);
// 保存更改...
}
}
}
}⚡ 性能优化策略
1. 对象池和缓存
csharp
/// <summary>
/// 使用对象池优化性能
/// </summary>
public class SyntaxNodePool
{
// 缓存常用的 token
private static readonly SyntaxToken PublicKeyword =
Token(SyntaxKind.PublicKeyword);
private static readonly SyntaxToken PrivateKeyword =
Token(SyntaxKind.PrivateKeyword);
private static readonly SyntaxToken StaticKeyword =
Token(SyntaxKind.StaticKeyword);
private static readonly SyntaxToken SemicolonToken =
Token(SyntaxKind.SemicolonToken);
// 缓存常用的类型
private static readonly Dictionary<string, TypeSyntax> TypeCache = new()
{
["string"] = PredefinedType(Token(SyntaxKind.StringKeyword)),
["int"] = PredefinedType(Token(SyntaxKind.IntKeyword)),
["bool"] = PredefinedType(Token(SyntaxKind.BoolKeyword)),
["void"] = PredefinedType(Token(SyntaxKind.VoidKeyword)),
["object"] = PredefinedType(Token(SyntaxKind.ObjectKeyword))
};
// 缓存常用的访问器
private static readonly AccessorDeclarationSyntax GetAccessor =
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(SemicolonToken);
private static readonly AccessorDeclarationSyntax SetAccessor =
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(SemicolonToken);
/// <summary>
/// 获取缓存的类型
/// </summary>
public static TypeSyntax GetType(string typeName)
{
if (TypeCache.TryGetValue(typeName, out var type))
{
return type;
}
// 如果不在缓存中,创建并缓存
type = ParseTypeName(typeName);
TypeCache[typeName] = type;
return type;
}
/// <summary>
/// 创建属性(使用缓存的节点)
/// </summary>
public static PropertyDeclarationSyntax CreateProperty(
string typeName,
string propertyName)
{
return PropertyDeclaration(GetType(typeName), propertyName)
.AddModifiers(PublicKeyword)
.AddAccessorListAccessors(GetAccessor, SetAccessor);
}
}2. 批量操作优化
csharp
/// <summary>
/// 批量操作优化示例
/// </summary>
public class BatchOperationOptimization
{
/// <summary>
/// ✅ 好的做法:批量添加成员
/// </summary>
public ClassDeclarationSyntax CreateClassOptimized(
string className,
List<PropertyInfo> properties)
{
// 一次性创建所有属性
var members = properties
.Select(p => SyntaxNodePool.CreateProperty(p.Type, p.Name))
.ToArray();
// 一次性添加所有成员
return ClassDeclaration(className)
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddMembers(members);
}
/// <summary>
/// ❌ 不好的做法:逐个添加成员
/// </summary>
public ClassDeclarationSyntax CreateClassSlow(
string className,
List<PropertyInfo> properties)
{
var classDecl = ClassDeclaration(className)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
// 每次调用 AddMembers 都会创建新对象
foreach (var prop in properties)
{
var property = SyntaxNodePool.CreateProperty(prop.Type, prop.Name);
classDecl = classDecl.AddMembers(property);
}
return classDecl;
}
public class PropertyInfo
{
public string Type { get; set; }
public string Name { get; set; }
}
}3. 延迟格式化
csharp
/// <summary>
/// 延迟格式化优化
/// </summary>
public class LazyFormattingOptimization
{
/// <summary>
/// ✅ 好的做法:最后才格式化
/// </summary>
public string GenerateMultipleClassesOptimized(List<string> classNames)
{
// 创建所有类(不格式化)
var classes = classNames
.Select(name => ClassDeclaration(name)
.AddModifiers(Token(SyntaxKind.PublicKeyword)))
.ToArray();
// 创建命名空间
var namespaceDecl = NamespaceDeclaration(ParseName("MyNamespace"))
.AddMembers(classes);
// 创建编译单元
var compilationUnit = CompilationUnit()
.AddMembers(namespaceDecl);
// 只在最后格式化一次
return compilationUnit.NormalizeWhitespace().ToFullString();
}
/// <summary>
/// ❌ 不好的做法:每次都格式化
/// </summary>
public string GenerateMultipleClassesSlow(List<string> classNames)
{
var sb = new StringBuilder();
foreach (var name in classNames)
{
var classDecl = ClassDeclaration(name)
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.NormalizeWhitespace(); // 每次都格式化
sb.AppendLine(classDecl.ToFullString());
}
return sb.ToString();
}
}4. 并行生成
csharp
/// <summary>
/// 并行代码生成
/// </summary>
public class ParallelCodeGeneration
{
/// <summary>
/// 并行生成多个类
/// </summary>
public CompilationUnitSyntax GenerateClassesInParallel(
List<ClassDefinition> definitions)
{
// 并行生成所有类
var classes = definitions
.AsParallel()
.Select(def => GenerateClass(def))
.ToArray();
// 组装成编译单元
return CompilationUnit()
.AddMembers(
NamespaceDeclaration(ParseName("Generated"))
.AddMembers(classes))
.NormalizeWhitespace();
}
private ClassDeclarationSyntax GenerateClass(ClassDefinition definition)
{
// 生成单个类的逻辑
return ClassDeclaration(definition.Name)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
}
public class ClassDefinition
{
public string Name { get; set; }
}
}5. 内存优化
csharp
/// <summary>
/// 内存优化技巧
/// </summary>
public class MemoryOptimization
{
/// <summary>
/// 使用 Span<T> 和 stackalloc 减少堆分配
/// </summary>
public string GenerateCodeWithSpan(ReadOnlySpan<char> className)
{
// 使用 stackalloc 在栈上分配小数组
Span<char> buffer = stackalloc char[256];
// 处理类名...
return ClassDeclaration(className.ToString())
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.NormalizeWhitespace()
.ToFullString();
}
/// <summary>
/// 使用 StringBuilder 池
/// </summary>
private static readonly ObjectPool<StringBuilder> StringBuilderPool =
new DefaultObjectPool<StringBuilder>(
new StringBuilderPooledObjectPolicy());
public string GenerateCodeWithPooledStringBuilder()
{
var sb = StringBuilderPool.Get();
try
{
// 使用 StringBuilder...
sb.AppendLine("public class MyClass");
sb.AppendLine("{");
sb.AppendLine("}");
return sb.ToString();
}
finally
{
StringBuilderPool.Return(sb);
}
}
}🎨 高级代码模式
访问者模式实现
csharp
/// <summary>
/// 使用访问者模式遍历和修改语法树
/// </summary>
public class SyntaxVisitorExample : CSharpSyntaxWalker
{
private readonly List<string> _classNames = new();
/// <summary>
/// 访问类声明
/// </summary>
public override void VisitClassDeclaration(ClassDeclarationSyntax node)
{
_classNames.Add(node.Identifier.Text);
// 继续访问子节点
base.VisitClassDeclaration(node);
}
/// <summary>
/// 获取所有类名
/// </summary>
public IReadOnlyList<string> GetClassNames(SyntaxNode root)
{
_classNames.Clear();
Visit(root);
return _classNames;
}
}策略模式用于代码生成
csharp
/// <summary>
/// 代码生成策略接口
/// </summary>
public interface ICodeGenerationStrategy
{
MemberDeclarationSyntax Generate(PropertyInfo property);
}
/// <summary>
/// 自动属性生成策略
/// </summary>
public class AutoPropertyStrategy : ICodeGenerationStrategy
{
public MemberDeclarationSyntax Generate(PropertyInfo property)
{
return PropertyDeclaration(
ParseTypeName(property.Type),
property.Name)
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
}
}
/// <summary>
/// 字段支持的属性生成策略
/// </summary>
public class BackingFieldPropertyStrategy : ICodeGenerationStrategy
{
public MemberDeclarationSyntax Generate(PropertyInfo property)
{
// 生成带后备字段的属性
// 实现略...
return null;
}
}
/// <summary>
/// 使用策略模式的代码生成器
/// </summary>
public class StrategyBasedGenerator
{
private readonly ICodeGenerationStrategy _strategy;
public StrategyBasedGenerator(ICodeGenerationStrategy strategy)
{
_strategy = strategy;
}
public ClassDeclarationSyntax GenerateClass(
string className,
List<PropertyInfo> properties)
{
var members = properties
.Select(p => _strategy.Generate(p))
.ToArray();
return ClassDeclaration(className)
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddMembers(members);
}
}
public class PropertyInfo
{
public string Type { get; set; }
public string Name { get; set; }
}🔍 边缘情况处理
处理特殊字符和标识符
csharp
/// <summary>
/// 处理特殊字符和保留字
/// </summary>
public class SpecialCharacterHandling
{
/// <summary>
/// 转义保留字
/// </summary>
public string EscapeReservedKeyword(string identifier)
{
var keywords = new HashSet<string>
{
"class", "public", "private", "int", "string", "void",
"if", "else", "for", "while", "return", "new"
};
return keywords.Contains(identifier) ? $"@{identifier}" : identifier;
}
/// <summary>
/// 创建安全的标识符
/// </summary>
public IdentifierNameSyntax CreateSafeIdentifier(string name)
{
var safeName = EscapeReservedKeyword(name);
return IdentifierName(safeName);
}
/// <summary>
/// 处理包含特殊字符的字符串
/// </summary>
public LiteralExpressionSyntax CreateStringLiteral(string value)
{
// Roslyn 会自动处理转义
return LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal(value));
}
/// <summary>
/// 创建 verbatim 字符串
/// </summary>
public LiteralExpressionSyntax CreateVerbatimString(string value)
{
return LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal(value, value)); // 第二个参数是原始值
}
}处理 Nullable 引用类型
csharp
/// <summary>
/// 处理 C# 8.0+ 的 nullable 引用类型
/// </summary>
public class NullableReferenceTypeHandling
{
/// <summary>
/// 创建 nullable 引用类型属性
/// public string? Name { get; set; }
/// </summary>
public PropertyDeclarationSyntax CreateNullableProperty(
string typeName,
string propertyName,
bool isNullable)
{
TypeSyntax type = ParseTypeName(typeName);
// 如果是引用类型且可空,添加 ? 标记
if (isNullable && IsReferenceType(typeName))
{
type = NullableType(type);
}
return PropertyDeclaration(type, propertyName)
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
}
private bool IsReferenceType(string typeName)
{
var valueTypes = new HashSet<string>
{
"int", "long", "short", "byte", "sbyte",
"uint", "ulong", "ushort",
"float", "double", "decimal",
"bool", "char",
"DateTime", "DateTimeOffset", "TimeSpan", "Guid"
};
return !valueTypes.Contains(typeName);
}
}处理泛型类型参数
csharp
/// <summary>
/// 处理复杂的泛型类型
/// </summary>
public class GenericTypeHandling
{
/// <summary>
/// 解析泛型类型字符串
/// 例如: "List<Dictionary<string, int>>"
/// </summary>
public TypeSyntax ParseGenericType(string typeString)
{
// 简单实现:使用 ParseTypeName
return ParseTypeName(typeString);
}
/// <summary>
/// 创建嵌套泛型类型
/// Dictionary<string, List<int>>
/// </summary>
public TypeSyntax CreateNestedGenericType()
{
return GenericName("Dictionary")
.AddTypeArgumentListArguments(
PredefinedType(Token(SyntaxKind.StringKeyword)),
GenericName("List")
.AddTypeArgumentListArguments(
PredefinedType(Token(SyntaxKind.IntKeyword))));
}
/// <summary>
/// 创建带约束的泛型方法
/// public T Create<T>() where T : new()
/// </summary>
public MethodDeclarationSyntax CreateGenericMethodWithConstraint()
{
return MethodDeclaration(
IdentifierName("T"),
"Create")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddTypeParameterListParameters(TypeParameter("T"))
.AddConstraintClauses(
TypeParameterConstraintClause("T")
.AddConstraints(ConstructorConstraint()))
.WithBody(Block(
ReturnStatement(
ObjectCreationExpression(IdentifierName("T"))
.WithArgumentList(ArgumentList()))));
}
}🧪 测试和验证
单元测试代码生成
csharp
using Xunit;
/// <summary>
/// 代码生成单元测试
/// </summary>
public class CodeGenerationTests
{
[Fact]
public void GenerateClass_WithProperties_ShouldCreateValidCode()
{
// Arrange
var generator = new FluentClassBuilder("Person");
// Act
var classDecl = generator
.WithModifier(SyntaxKind.PublicKeyword)
.WithMember(SyntaxNodePool.CreateProperty("string", "Name"))
.WithMember(SyntaxNodePool.CreateProperty("int", "Age"))
.Build();
var code = classDecl.NormalizeWhitespace().ToFullString();
// Assert
Assert.Contains("public class Person", code);
Assert.Contains("public string Name { get; set; }", code);
Assert.Contains("public int Age { get; set; }", code);
}
[Fact]
public void GenerateGenericClass_WithConstraints_ShouldBeValid()
{
// Arrange & Act
var classDecl = new AdvancedGenericClassGeneration()
.GenerateRepositoryClass();
var code = classDecl.NormalizeWhitespace().ToFullString();
// Assert
Assert.Contains("public class Repository<TEntity, TKey>", code);
Assert.Contains("where TEntity : class", code);
Assert.Contains("where TKey : struct", code);
}
[Theory]
[InlineData("class", "@class")]
[InlineData("public", "@public")]
[InlineData("myVar", "myVar")]
public void EscapeReservedKeyword_ShouldHandleCorrectly(
string input,
string expected)
{
// Arrange
var handler = new SpecialCharacterHandling();
// Act
var result = handler.EscapeReservedKeyword(input);
// Assert
Assert.Equal(expected, result);
}
}集成测试
csharp
/// <summary>
/// 集成测试:验证生成的代码可以编译
/// </summary>
public class CodeCompilationTests
{
[Fact]
public void GeneratedCode_ShouldCompile()
{
// Arrange
var generator = new FluentClassBuilder("TestClass");
var classDecl = generator
.WithModifier(SyntaxKind.PublicKeyword)
.WithMember(SyntaxNodePool.CreateProperty("string", "Name"))
.Build();
var compilationUnit = CompilationUnit()
.AddUsings(UsingDirective(ParseName("System")))
.AddMembers(
NamespaceDeclaration(ParseName("TestNamespace"))
.AddMembers(classDecl))
.NormalizeWhitespace();
var code = compilationUnit.ToFullString();
// Act
var syntaxTree = CSharpSyntaxTree.ParseText(code);
var compilation = CSharpCompilation.Create(
"TestAssembly",
new[] { syntaxTree },
new[]
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location)
},
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
var diagnostics = compilation.GetDiagnostics();
// Assert
var errors = diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error);
Assert.Empty(errors);
}
}性能基准测试
csharp
using BenchmarkDotNet.Attributes;
/// <summary>
/// 性能基准测试
/// </summary>
[MemoryDiagnoser]
public class CodeGenerationBenchmarks
{
private List<PropertyInfo> _properties;
[GlobalSetup]
public void Setup()
{
_properties = Enumerable.Range(0, 100)
.Select(i => new PropertyInfo
{
Type = "string",
Name = $"Property{i}"
})
.ToList();
}
[Benchmark]
public ClassDeclarationSyntax GenerateClass_Optimized()
{
return new BatchOperationOptimization()
.CreateClassOptimized("TestClass", _properties);
}
[Benchmark]
public ClassDeclarationSyntax GenerateClass_Slow()
{
return new BatchOperationOptimization()
.CreateClassSlow("TestClass", _properties);
}
public class PropertyInfo
{
public string Type { get; set; }
public string Name { get; set; }
}
}💡 实战案例
案例 1: 自动生成 DTO 映射代码
csharp
/// <summary>
/// 自动生成 DTO 到实体的映射代码
/// </summary>
public class DtoMappingGenerator
{
/// <summary>
/// 生成映射方法
/// public static Entity ToEntity(this EntityDto dto)
/// {
/// return new Entity
/// {
/// Id = dto.Id,
/// Name = dto.Name,
/// // ...
/// };
/// }
/// </summary>
public MethodDeclarationSyntax GenerateMappingMethod(
string dtoTypeName,
string entityTypeName,
List<string> propertyNames)
{
// 创建对象初始化器
var initializers = propertyNames.Select(propName =>
AssignmentExpression(
SyntaxKind.SimpleAssignmentExpression,
IdentifierName(propName),
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName("dto"),
IdentifierName(propName))));
return MethodDeclaration(
IdentifierName(entityTypeName),
"ToEntity")
.AddModifiers(
Token(SyntaxKind.PublicKeyword),
Token(SyntaxKind.StaticKeyword))
.AddParameterListParameters(
Parameter(Identifier("dto"))
.WithType(IdentifierName(dtoTypeName))
.WithModifiers(TokenList(Token(SyntaxKind.ThisKeyword))))
.WithBody(Block(
ReturnStatement(
ObjectCreationExpression(IdentifierName(entityTypeName))
.WithInitializer(
InitializerExpression(
SyntaxKind.ObjectInitializerExpression,
SeparatedList<ExpressionSyntax>(initializers))))));
}
}案例 2: 生成验证代码
csharp
/// <summary>
/// 自动生成数据验证代码
/// </summary>
public class ValidationCodeGenerator
{
/// <summary>
/// 生成验证方法
/// public bool Validate(out List<string> errors)
/// {
/// errors = new List<string>();
///
/// if (string.IsNullOrEmpty(Name))
/// errors.Add("Name is required");
///
/// if (Age < 0)
/// errors.Add("Age must be positive");
///
/// return errors.Count == 0;
/// }
/// </summary>
public MethodDeclarationSyntax GenerateValidationMethod(
List<ValidationRule> rules)
{
var statements = new List<StatementSyntax>();
// errors = new List<string>();
statements.Add(
ExpressionStatement(
AssignmentExpression(
SyntaxKind.SimpleAssignmentExpression,
IdentifierName("errors"),
ObjectCreationExpression(
GenericName("List")
.AddTypeArgumentListArguments(
PredefinedType(Token(SyntaxKind.StringKeyword))))
.WithArgumentList(ArgumentList()))));
// 为每个规则生成验证代码
foreach (var rule in rules)
{
statements.Add(GenerateValidationStatement(rule));
}
// return errors.Count == 0;
statements.Add(
ReturnStatement(
BinaryExpression(
SyntaxKind.EqualsExpression,
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName("errors"),
IdentifierName("Count")),
LiteralExpression(
SyntaxKind.NumericLiteralExpression,
Literal(0)))));
return MethodDeclaration(
PredefinedType(Token(SyntaxKind.BoolKeyword)),
"Validate")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddParameterListParameters(
Parameter(Identifier("errors"))
.WithType(
GenericName("List")
.AddTypeArgumentListArguments(
PredefinedType(Token(SyntaxKind.StringKeyword))))
.WithModifiers(TokenList(Token(SyntaxKind.OutKeyword))))
.WithBody(Block(statements));
}
private StatementSyntax GenerateValidationStatement(ValidationRule rule)
{
// if (condition)
// errors.Add("error message");
return IfStatement(
ParseExpression(rule.Condition),
ExpressionStatement(
InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName("errors"),
IdentifierName("Add")))
.AddArgumentListArguments(
Argument(
LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal(rule.ErrorMessage))))));
}
public class ValidationRule
{
public string Condition { get; set; }
public string ErrorMessage { get; set; }
}
}案例 3: 生成序列化代码
csharp
/// <summary>
/// 自动生成序列化/反序列化代码
/// </summary>
public class SerializationCodeGenerator
{
/// <summary>
/// 生成 JSON 序列化方法
/// public string ToJson()
/// {
/// return JsonSerializer.Serialize(this);
/// }
/// </summary>
public MethodDeclarationSyntax GenerateToJsonMethod()
{
return MethodDeclaration(
PredefinedType(Token(SyntaxKind.StringKeyword)),
"ToJson")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.WithBody(Block(
ReturnStatement(
InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName("JsonSerializer"),
IdentifierName("Serialize")))
.AddArgumentListArguments(
Argument(ThisExpression())))));
}
/// <summary>
/// 生成 JSON 反序列化方法
/// public static T FromJson<T>(string json)
/// {
/// return JsonSerializer.Deserialize<T>(json);
/// }
/// </summary>
public MethodDeclarationSyntax GenerateFromJsonMethod()
{
return MethodDeclaration(
IdentifierName("T"),
"FromJson")
.AddModifiers(
Token(SyntaxKind.PublicKeyword),
Token(SyntaxKind.StaticKeyword))
.AddTypeParameterListParameters(TypeParameter("T"))
.AddParameterListParameters(
Parameter(Identifier("json"))
.WithType(PredefinedType(Token(SyntaxKind.StringKeyword))))
.WithBody(Block(
ReturnStatement(
InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName("JsonSerializer"),
GenericName("Deserialize")
.AddTypeArgumentListArguments(IdentifierName("T"))))
.AddArgumentListArguments(
Argument(IdentifierName("json"))))));
}
}📚 最佳实践总结
✅ 推荐做法
使用对象池和缓存
- 缓存常用的 token 和语法节点
- 重用不可变对象
批量操作
- 一次性添加所有成员
- 避免在循环中逐个添加
延迟格式化
- 只在最后格式化一次
- 避免重复格式化
使用流式构建器
- 提高代码可读性
- 支持链式调用
编写单元测试
- 验证生成的代码正确性
- 使用基准测试优化性能
❌ 避免的做法
不要在循环中格式化
- 性能开销大
- 应该最后统一格式化
不要逐个添加成员
- 每次都创建新对象
- 应该批量添加
不要忽略边缘情况
- 保留字需要转义
- 特殊字符需要处理
不要过度优化
- 先保证正确性
- 再考虑性能优化
🔗 相关资源
API 参考
完整参考
- 代码生成 API 完整参考 - 完整文档
实战示例
- Builder 生成器 - 实战案例
- ToString 生成器 - 实战案例
⏭️ 下一步
完成本指南后,建议:
- 实践项目 - 创建一个复杂的代码生成器
- 性能优化 - 使用基准测试优化性能
- 学习增量生成 - 掌握增量生成器
- 阅读源码 - 研究 Roslyn 源代码
最后更新: 2025-01-21