代码构建模式
📋 文档信息
难度: 🟡 中级
预计阅读时间: 20 分钟
前置知识:
- SyntaxFactory 基础
- C# 设计模式基础
- 面向对象编程
适合人群:
- 需要组织复杂代码生成逻辑的开发者
- 源生成器架构师
- 代码生成工具开发者
📋 快速导航
| 章节 | 难度 | 阅读时间 | 链接 |
|---|---|---|---|
| 构建器模式 | 🟡 | 8 分钟 | 查看 |
| 流式 API | 🟢 | 5 分钟 | 查看 |
| 模板方法模式 | 🟡 | 7 分钟 | 查看 |
🎯 概览
本文档介绍在代码生成中常用的设计模式和最佳实践,帮助你组织和维护复杂的代码生成逻辑。
本文档涵盖:
- 构建器模式的应用
- 流式 API 的设计
- 模板方法模式
- 代码复用技巧
典型应用场景:
- 复杂类结构的生成
- 可配置的代码生成器
- 代码生成框架设计
构建器模式
使用构建器模式可以让代码生成更加清晰和易于维护。
基本构建器
csharp
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
using System.Collections.Generic;
using System.Linq;
/// <summary>
/// 类构建器
/// </summary>
public class ClassBuilder
{
private string _className;
private List<string> _modifiers = new();
private List<PropertyDeclarationSyntax> _properties = new();
private List<MethodDeclarationSyntax> _methods = new();
public ClassBuilder WithName(string name)
{
_className = name;
return this;
}
public ClassBuilder WithModifier(string modifier)
{
_modifiers.Add(modifier);
return this;
}
public ClassBuilder AddProperty(string type, string name)
{
var property = PropertyDeclaration(
ParseTypeName(type),
Identifier(name))
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
_properties.Add(property);
return this;
}
public ClassDeclarationSyntax Build()
{
var classDecl = ClassDeclaration(_className);
// 添加修饰符
foreach (var modifier in _modifiers)
{
classDecl = classDecl.AddModifiers(
Token(ParseModifier(modifier)));
}
// 添加成员
classDecl = classDecl.AddMembers(_properties.ToArray());
classDecl = classDecl.AddMembers(_methods.ToArray());
return classDecl;
}
private SyntaxKind ParseModifier(string modifier)
{
return modifier.ToLower() switch
{
"public" => SyntaxKind.PublicKeyword,
"private" => SyntaxKind.PrivateKeyword,
"protected" => SyntaxKind.ProtectedKeyword,
"internal" => SyntaxKind.InternalKeyword,
"static" => SyntaxKind.StaticKeyword,
"abstract" => SyntaxKind.AbstractKeyword,
"sealed" => SyntaxKind.SealedKeyword,
_ => throw new ArgumentException($"Unknown modifier: {modifier}")
};
}
}使用构建器
csharp
/// <summary>
/// 使用构建器生成类
/// </summary>
public class BuilderUsageExample
{
public ClassDeclarationSyntax GeneratePersonClass()
{
return new ClassBuilder()
.WithName("Person")
.WithModifier("public")
.AddProperty("string", "FirstName")
.AddProperty("string", "LastName")
.AddProperty("int", "Age")
.Build();
}
}增强的构建器
csharp
/// <summary>
/// 增强的类构建器,支持更多功能
/// </summary>
public class EnhancedClassBuilder
{
private string _className;
private List<SyntaxToken> _modifiers = new();
private List<PropertyDeclarationSyntax> _properties = new();
private List<MethodDeclarationSyntax> _methods = new();
private List<FieldDeclarationSyntax> _fields = new();
private List<ConstructorDeclarationSyntax> _constructors = new();
private List<string> _baseTypes = new();
private List<AttributeListSyntax> _attributes = new();
public EnhancedClassBuilder WithName(string name)
{
_className = name;
return this;
}
public EnhancedClassBuilder WithModifier(string modifier)
{
_modifiers.Add(Token(ParseModifier(modifier)));
return this;
}
public EnhancedClassBuilder AddProperty(string type, string name)
{
var property = PropertyDeclaration(
ParseTypeName(type),
Identifier(name))
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
_properties.Add(property);
return this;
}
public EnhancedClassBuilder AddMethod(MethodDeclarationSyntax method)
{
_methods.Add(method);
return this;
}
public EnhancedClassBuilder AddField(string type, string name, bool isReadOnly = false)
{
var modifiers = new List<SyntaxToken> { Token(SyntaxKind.PrivateKeyword) };
if (isReadOnly)
{
modifiers.Add(Token(SyntaxKind.ReadOnlyKeyword));
}
var field = FieldDeclaration(
VariableDeclaration(ParseTypeName(type))
.AddVariables(VariableDeclarator(Identifier(name))))
.AddModifiers(modifiers.ToArray());
_fields.Add(field);
return this;
}
public EnhancedClassBuilder AddConstructor(ConstructorDeclarationSyntax constructor)
{
_constructors.Add(constructor);
return this;
}
public EnhancedClassBuilder WithBaseType(string baseType)
{
_baseTypes.Add(baseType);
return this;
}
public EnhancedClassBuilder AddAttribute(AttributeListSyntax attribute)
{
_attributes.Add(attribute);
return this;
}
public ClassDeclarationSyntax Build()
{
var classDecl = ClassDeclaration(_className);
// 添加特性
if (_attributes.Any())
{
classDecl = classDecl.AddAttributeLists(_attributes.ToArray());
}
// 添加修饰符
if (_modifiers.Any())
{
classDecl = classDecl.AddModifiers(_modifiers.ToArray());
}
// 添加基类和接口
if (_baseTypes.Any())
{
classDecl = classDecl.AddBaseListTypes(
_baseTypes.Select(bt => SimpleBaseType(IdentifierName(bt))).ToArray());
}
// 添加成员(按顺序:字段、构造函数、属性、方法)
var members = new List<MemberDeclarationSyntax>();
members.AddRange(_fields);
members.AddRange(_constructors);
members.AddRange(_properties);
members.AddRange(_methods);
classDecl = classDecl.AddMembers(members.ToArray());
return classDecl;
}
private SyntaxKind ParseModifier(string modifier)
{
return modifier.ToLower() switch
{
"public" => SyntaxKind.PublicKeyword,
"private" => SyntaxKind.PrivateKeyword,
"protected" => SyntaxKind.ProtectedKeyword,
"internal" => SyntaxKind.InternalKeyword,
"static" => SyntaxKind.StaticKeyword,
"abstract" => SyntaxKind.AbstractKeyword,
"sealed" => SyntaxKind.SealedKeyword,
"partial" => SyntaxKind.PartialKeyword,
_ => throw new ArgumentException($"Unknown modifier: {modifier}")
};
}
}流式 API
流式 API 允许你以链式调用的方式构建代码,使代码更简洁易读。
基本流式 API
csharp
/// <summary>
/// 使用流式 API 生成代码
/// </summary>
public class FluentCodeGeneration
{
public ClassDeclarationSyntax GenerateClass()
{
return ClassDeclaration("MyClass")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddMembers(
PropertyDeclaration(
PredefinedType(Token(SyntaxKind.StringKeyword)),
"Name")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken))));
}
}扩展方法增强流式 API
csharp
/// <summary>
/// 扩展方法,增强流式 API
/// </summary>
public static class SyntaxExtensions
{
/// <summary>
/// 添加公共自动属性
/// </summary>
public static ClassDeclarationSyntax AddAutoProperty(
this ClassDeclarationSyntax classDecl,
string typeName,
string propertyName)
{
var property = PropertyDeclaration(
ParseTypeName(typeName),
Identifier(propertyName))
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
return classDecl.AddMembers(property);
}
/// <summary>
/// 添加只读属性
/// </summary>
public static ClassDeclarationSyntax AddReadOnlyProperty(
this ClassDeclarationSyntax classDecl,
string typeName,
string propertyName)
{
var property = PropertyDeclaration(
ParseTypeName(typeName),
Identifier(propertyName))
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
return classDecl.AddMembers(property);
}
/// <summary>
/// 添加私有字段
/// </summary>
public static ClassDeclarationSyntax AddPrivateField(
this ClassDeclarationSyntax classDecl,
string typeName,
string fieldName,
bool isReadOnly = false)
{
var modifiers = new List<SyntaxToken> { Token(SyntaxKind.PrivateKeyword) };
if (isReadOnly)
{
modifiers.Add(Token(SyntaxKind.ReadOnlyKeyword));
}
var field = FieldDeclaration(
VariableDeclaration(ParseTypeName(typeName))
.AddVariables(VariableDeclarator(Identifier(fieldName))))
.AddModifiers(modifiers.ToArray());
return classDecl.AddMembers(field);
}
}使用扩展方法
csharp
/// <summary>
/// 使用扩展方法的流式 API
/// </summary>
public class FluentWithExtensions
{
public ClassDeclarationSyntax GeneratePersonClass()
{
return ClassDeclaration("Person")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAutoProperty("string", "FirstName")
.AddAutoProperty("string", "LastName")
.AddAutoProperty("int", "Age")
.AddReadOnlyProperty("string", "FullName")
.AddPrivateField("string", "_internalId", isReadOnly: true);
}
}模板方法模式
模板方法模式定义了代码生成的骨架,让子类可以重写特定步骤。
基础模板类
csharp
/// <summary>
/// 代码生成器基类
/// </summary>
public abstract class CodeGeneratorBase
{
/// <summary>
/// 模板方法:定义代码生成的整体流程
/// </summary>
public CompilationUnitSyntax Generate()
{
var compilationUnit = CompilationUnit();
// 1. 添加 using 指令
compilationUnit = AddUsings(compilationUnit);
// 2. 创建命名空间
var namespaceDecl = CreateNamespace();
// 3. 创建类
var classDecl = CreateClass();
// 4. 添加成员
classDecl = AddMembers(classDecl);
// 5. 组装
namespaceDecl = namespaceDecl.AddMembers(classDecl);
compilationUnit = compilationUnit.AddMembers(namespaceDecl);
// 6. 格式化
return compilationUnit.NormalizeWhitespace();
}
/// <summary>
/// 添加 using 指令(可重写)
/// </summary>
protected virtual CompilationUnitSyntax AddUsings(CompilationUnitSyntax compilationUnit)
{
return compilationUnit.AddUsings(
UsingDirective(ParseName("System")));
}
/// <summary>
/// 创建命名空间(可重写)
/// </summary>
protected abstract NamespaceDeclarationSyntax CreateNamespace();
/// <summary>
/// 创建类(必须实现)
/// </summary>
protected abstract ClassDeclarationSyntax CreateClass();
/// <summary>
/// 添加成员(可重写)
/// </summary>
protected virtual ClassDeclarationSyntax AddMembers(ClassDeclarationSyntax classDecl)
{
return classDecl;
}
}具体实现类
csharp
/// <summary>
/// DTO 生成器
/// </summary>
public class DtoGenerator : CodeGeneratorBase
{
private readonly string _className;
private readonly List<PropertyInfo> _properties;
public DtoGenerator(string className, List<PropertyInfo> properties)
{
_className = className;
_properties = properties;
}
protected override NamespaceDeclarationSyntax CreateNamespace()
{
return NamespaceDeclaration(ParseName("MyApp.Dtos"));
}
protected override ClassDeclarationSyntax CreateClass()
{
return ClassDeclaration(_className)
.AddModifiers(Token(SyntaxKind.PublicKeyword));
}
protected override ClassDeclarationSyntax AddMembers(ClassDeclarationSyntax classDecl)
{
foreach (var prop in _properties)
{
var property = PropertyDeclaration(
ParseTypeName(prop.Type),
Identifier(prop.Name))
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
classDecl = classDecl.AddMembers(property);
}
return classDecl;
}
public class PropertyInfo
{
public string Name { get; set; }
public string Type { get; set; }
}
}💡 最佳实践
实践 1: 选择合适的模式
csharp
// ✅ 好:简单场景使用流式 API
var simpleClass = ClassDeclaration("Simple")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddMembers(property1, property2);
// ✅ 好:复杂场景使用构建器模式
var complexClass = new ClassBuilder()
.WithName("Complex")
.WithModifier("public")
.AddProperty("string", "Name")
.AddMethod(method1)
.AddField("int", "_id")
.Build();原因: 根据复杂度选择合适的模式,简单场景不要过度设计。
实践 2: 使用扩展方法增强可读性
csharp
// ✅ 好:使用扩展方法
var classDecl = ClassDeclaration("Person")
.AddAutoProperty("string", "Name")
.AddAutoProperty("int", "Age");
// ❌ 差:重复的冗长代码
var classDecl = ClassDeclaration("Person")
.AddMembers(
PropertyDeclaration(...) // 重复的代码
.AddModifiers(...)
.AddAccessorListAccessors(...),
PropertyDeclaration(...) // 重复的代码
.AddModifiers(...)
.AddAccessorListAccessors(...));原因: 扩展方法可以封装常用操作,提高代码可读性和可维护性。
实践 3: 保持构建器的不可变性
csharp
// ✅ 好:每个方法返回新的构建器实例
public class ImmutableClassBuilder
{
private readonly string _className;
private readonly ImmutableList<PropertyDeclarationSyntax> _properties;
public ImmutableClassBuilder WithName(string name)
{
return new ImmutableClassBuilder(name, _properties);
}
public ImmutableClassBuilder AddProperty(PropertyDeclarationSyntax property)
{
return new ImmutableClassBuilder(_className, _properties.Add(property));
}
}原因: 不可变性使构建器更安全,避免意外修改。
⚠️ 常见错误
错误 1: 构建器状态管理混乱
问题: 构建器的状态没有正确管理,导致生成的代码不正确。
csharp
// ❌ 错误:忘记返回 this
public class BadBuilder
{
public void AddProperty(string name)
{
// 忘记返回 this,无法链式调用
_properties.Add(CreateProperty(name));
}
}解决方案:
csharp
// ✅ 正确:返回 this 支持链式调用
public class GoodBuilder
{
public GoodBuilder AddProperty(string name)
{
_properties.Add(CreateProperty(name));
return this;
}
}错误 2: 过度使用模式
问题: 在简单场景中使用复杂的设计模式,增加不必要的复杂度。
csharp
// ❌ 错误:简单场景使用复杂模式
var builder = new ComplexBuilder()
.WithStrategy(new DefaultStrategy())
.WithFactory(new PropertyFactory())
.WithValidator(new Validator())
.AddProperty("Name"); // 只是添加一个属性而已解决方案:
csharp
// ✅ 正确:简单场景使用简单方法
var property = PropertyDeclaration(
PredefinedType(Token(SyntaxKind.StringKeyword)),
"Name")
.AddModifiers(Token(SyntaxKind.PublicKeyword))
.AddAccessorListAccessors(
AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));🔗 相关文档
- 返回索引
- SyntaxFactory 基础 - 学习 SyntaxFactory 的基本使用
- SyntaxFactory 高级 - 学习复杂结构的生成技术
- 格式化和美化 - 学习如何格式化生成的代码
- 最佳实践 - 掌握代码生成的最佳实践
其他相关文档
📚 下一步
学习完本文档后,建议继续学习:
最后更新: 2026-02-05
文档版本: 1.0