Skip to content

代码构建模式

📋 文档信息

难度: 🟡 中级
预计阅读时间: 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)));

🔗 相关文档

其他相关文档


📚 下一步

学习完本文档后,建议继续学习:

  1. 格式化和美化 - 学习如何格式化生成的代码
  2. 最佳实践 - 掌握代码生成的最佳实践和性能优化
  3. 实战示例 - 查看完整的源生成器示例

最后更新: 2026-02-05
文档版本: 1.0

基于 MIT 许可发布