1. 项目概述:全栈开发的自动化革命

在过去的几年里,我深度参与了多个基于 ASP.NET Core Web API 和 Angular 的企业级项目。一个反复出现的痛点让我印象深刻:从零开始搭建一个具备基础 CRUD、用户认证、权限管理和前端路由的模块,往往需要耗费数天时间,而且这个过程充斥着大量重复、机械且容易出错的代码编写工作。后端要定义实体模型、创建 DbContext、编写控制器、配置依赖注入、实现仓储模式;前端则要生成服务、组件、模板、路由,并确保类型安全。这不仅是效率问题,更严重的是,它消耗了开发者最宝贵的创造力和解决复杂业务逻辑的精力。

“Automate Your Full-stack Development on ASP.NET Core Web API and Angular With Code Generator and AI Code Agent”这个项目,正是为了解决这一核心痛点而生。它不是一个单一的工具,而是一套结合了传统代码生成器的确定性与现代 AI 代码代理的智能性的自动化工作流。简单来说,它能让你通过一个简单的领域模型定义,自动生成前后端所有的基础架构代码,并借助 AI 的上下文理解能力,辅助你完成更复杂的业务逻辑填充和代码优化。这套方案适合任何正在或计划使用 .NET 技术栈进行全栈开发的团队,无论是初创公司快速验证产品,还是大型团队需要统一架构规范、提升交付速度,都能从中获得巨大收益。其核心价值在于,将开发者从“脚手架工人”的角色中解放出来,使其能更专注于业务创新和系统架构设计。

2. 自动化全栈工作流的核心设计思路

2.1 为何选择“生成器+AI代理”的双引擎模式

传统的代码生成器(如早期的 CodeSmith、T4 Templates,或 Entity Framework 的 Scaffold-DbContext)能力边界清晰:基于模板和输入(如数据库表、Swagger 定义),生成结构固定、可预测的代码。它的优势是速度快、结果稳定、符合预设规范,非常适合生成那些模式固定的“样板代码”,比如实体类、基础的 API 端点、数据访问层接口。然而,它的短板同样明显:缺乏灵活性,无法理解业务上下文,更无法处理模板之外的非标准逻辑。

AI 代码代理(例如基于 GPT-4、Claude 3 等大语言模型构建的智能助手)则代表了另一种范式。它能够理解自然语言指令和现有代码的上下文,进行推理、创作和修改。你可以让它“为这个 Product 实体添加一个计算折扣价的方法,需要考虑会员等级”,它能生成符合上下文的、语法正确的代码。但其生成结果具有不确定性,可能每次略有不同,且对于需要严格遵循特定项目架构和命名规范的大规模、结构化代码生成,效率并不高。

因此,本方案采用了“生成器打地基,AI 代理搞装修”的协同策略。代码生成器负责搭建整个项目的骨架和管道——创建符合 Onion/Clean Architecture 的分层项目结构,生成所有实体、DTO、控制器、服务接口和 Angular 的服务、组件文件。这一步确保了项目的基础架构是统一、健壮且可维护的。随后,AI 代码代理在这个生成好的、结构清晰的代码基上工作,负责填充那些需要“智能”和“创意”的部分,比如复杂的业务验证逻辑、特定的算法实现、或者根据一段业务描述生成某个服务方法的具体实现。这种分工结合了二者的优点,既保证了效率和规范性,又引入了灵活性和智能化。

2.2 技术栈选型与工具链构建

要实现这一工作流,我们需要精心挑选和整合一系列工具。

后端(ASP.NET Core Web API)核心生成器: 我强烈推荐并采用 NSwag Swashbuckle NJsonSchema 的深度结合,而不仅仅是用于生成 API 文档。通过定义详细的、带有丰富数据注解(如 [Required] , [StringLength] )的 C# 模型,我们可以利用 NSwag 的代码生成功能,不仅产生 OpenAPI 规范,更能直接生成强类型的 TypeScript 客户端代码(包括请求/响应模型和服务类)。这是连接前后端类型安全的关键桥梁。对于更复杂的领域驱动设计(DDD)代码生成,可以扩展使用 T4 Templates 或更现代的 Razor Engine 来定制模板,根据领域模型文件(可以是简单的 JSON 或 YAML)生成实体、值对象、仓储接口等。

前端(Angular)配套生成器: Angular CLI 本身就是一个强大的生成器。我们可以通过创建自定义的 Schematics 来扩展它。例如,我们可以编写一个 Schematic,它读取由后端 NSwag 生成的 TypeScript 模型接口,然后自动生成对应的 Angular 组件(包含 HTML 模板和 CSS)、路由模块、以及注入并使用了强类型服务的功能模块。这样,前后端的类型从数据库到 UI 保持了一致性。

AI 代码代理的集成: 这里的选择更多样。你可以使用 GitHub Copilot Cursor 作为开发环境中的实时助手。但对于流程化集成,更有效的方式是利用 OpenAI API Anthropic Claude API 构建一个定制的自动化脚本。这个脚本的工作流程是:1)读取刚刚由代码生成器创建的文件;2)结合项目特定的上下文(如架构说明、现有类似模块的代码)构造精准的提示词(Prompt);3)调用 AI API 生成目标代码片段;4)将生成的代码插入到文件的适当位置(例如,向一个生成的空服务类中添加具体的方法实现)。关键在于构建高质量的“上下文”,这通常需要将相关代码文件、项目结构文档作为提示词的一部分喂给 AI。

编排与自动化: 最后,我们需要一个“胶水”将这一切粘合起来。一个简单的 Node.js 脚本 PowerShell 脚本 就能胜任。更工程化的做法是使用 Cake Build NUKE 这样的 .NET 构建自动化工具,定义一个完整的构建流水线,其中一步就是“代码生成与增强”。这个流水线的输入可能是一个领域模型定义文件,输出则是一个可以直接运行和开发的功能完整的模块。

3. 从零搭建自动化工作流的实操要点

3.1 第一步:定义统一的领域模型源

一切自动化的起点是有一个单一、权威的真相来源(Single Source of Truth)。我们不能让数据库设计、后端模型和前端的 TypeScript 接口各自为政。我实践下来最有效的方式是, 使用一个与具体技术无关的领域描述文件作为源头 。这个文件可以是一个简单的 JSON Schema,一个 YAML 文件,甚至是一个 Markdown 表格。它的核心是描述业务实体、属性和关系。

例如,我们可以定义一个 domain.models.yaml 文件:

entities:
  - name: Product
    properties:
      - name: Id
        type: guid
        isKey: true
      - name: Name
        type: string
        maxLength: 100
        isRequired: true
      - name: Description
        type: string
        maxLength: 500
      - name: Price
        type: decimal
        precision: 18
        scale: 2
        isRequired: true
      - name: CategoryId
        type: guid
        foreignKey: Category.Id
    endpoints:
      - GET /api/products
      - GET /api/products/{id}
      - POST /api/products
      - PUT /api/products/{id}
      - DELETE /api/products/{id}

这个文件将成为后续所有生成步骤的输入。它的优势在于人类可读、易于版本控制,并且将业务概念与技术实现解耦。

注意: 在定义模型时,务必提前考虑好验证规则(如必填、长度、范围)、导航属性(一对多、多对多关系)以及 API 端点的设计(是否支持分页、过滤、排序)。这些信息越详细,后续生成的代码就越完整,需要人工干预的地方就越少。

3.2 第二步:配置后端代码生成管道

有了领域模型,我们首先来生成 ASP.NET Core 的后端代码。这里我推荐一个组合拳:使用 自定义的 T4 模板 生成实体类和 DbContext,然后利用 NSwag 的代码生成能力来产生 API 控制器和 TypeScript 客户端。

1. 使用 T4 模板生成领域层和基础设施层代码: 在 Visual Studio 中创建一个 .tt 文本模板文件。这个模板会读取我们的 domain.models.yaml ,然后循环遍历每个实体,生成对应的 C# 类。模板的核心逻辑包括:

  • 根据 type 映射到 C# 类型( string -> string , decimal -> decimal )。
  • 根据 isRequired 等属性添加数据注解( [Required] )。
  • 根据 foreignKey 生成导航属性( public virtual Category Category { get; set; } )。 同时,可以生成一个 AppDbContext.cs ,其中包含所有的 DbSet<T> 属性。

2. 利用 NSwag 生成 API 层和客户端代码: 我们不在这个阶段手写控制器。相反,我们配置 NSwag,让它根据已经生成的、带有数据注解的实体类,自动生成 OpenAPI (Swagger) 规范。然后,再利用这个规范生成两样东西:

  • ASP.NET Core 控制器 :NSwag 可以提供一个名为 NSwag.Annotations 的包,通过装饰你的 DTO(可以用实体类本身,或专门生成的纯 DTO)和 API 接口,让 NSwag 在运行时动态生成控制器。但更常见的做法是,使用 NSwag Studio 或 NSwag CLI,以“代码优先”的方式,直接根据你的 C# 模型和约定,生成控制器代码文件。这需要你预先定义好一个基础的控制器模板。
  • TypeScript 客户端与服务模型 :这是 NSwag 的强项。执行一个命令,它就能生成一个完整的 api-client.ts 文件,里面包含了所有 API 端点的强类型调用函数(基于 fetch axios ),以及对应的请求/响应模型接口。这个文件将被前端 Angular 项目直接引用。

实操命令示例(使用 NSwag CLI):

# 从包含注解的C#程序集生成OpenAPI规范
nswag swagger2tsclient /input:MyApi.dll /output:../angular-client/src/app/api-client.ts /namespace:MyApp.Client /template:Angular

# 或者,从已启动的API端点实时获取规范并生成
nswag openapi2tsclient /input:http://localhost:5000/swagger/v1/swagger.json /output:../angular-client/src/app/api-client.ts

3.3 第三步:构建前端 Angular 的自动化脚手架

后端生成了强类型的 TypeScript 客户端,前端的工作就完成了一半。接下来,我们需要自动创建 Angular 组件来消费这些 API。

1. 创建自定义 Angular Schematic: Angular Schematic 是一个强大的代码生成和转换工具。我们可以创建一个自定义的 Schematic,它接收一个参数(例如实体名“Product”),然后执行以下操作:

  • src/app/features/ 目录下创建一个新的功能模块文件夹 product
  • 在该模块内生成标准的组件文件: product-list.component.ts/html/css product-detail.component.ts/html/css
  • 生成模块文件 product.module.ts 和路由文件 product-routing.module.ts
  • 最关键的一步: 读取由 NSwag 生成的 api-client.ts 文件 ,找到与“Product”相关的服务类(如 ProductClient )和模型接口(如 ProductDto ),然后将它们正确地导入和注入到生成的组件中。例如,在 product-list.component.ts 中,自动注入 ProductClient ,并在 ngOnInit 中调用 getAll() 方法,并将结果赋值给一个类型为 ProductDto[] 的数组。

2. 运行 Schematic: 开发人员只需要在终端输入一个命令:

ng generate my-schematics:crud-module --name=Product

一个完整的、具备列表、详情、创建、编辑、删除功能的 Product 功能模块就生成了,并且所有类型都是安全的,API 调用也是现成的。

实操心得: 在编写自定义 Schematic 时,最大的挑战是模板文件的灵活性和与动态数据的结合。建议使用 @schematics/angular 包提供的工具函数,如 applyTemplates mergeWith 。另外,一定要处理好路径问题,确保生成的文件放在正确的位置,并且模块声明和路由配置能正确更新 AppModule

4. 引入 AI 代码代理进行智能增强

至此,我们已经有了一个可以运行的全栈 CRUD 模块,但所有业务逻辑(除了简单的增删改查)都是空的。这就是 AI 代理大显身手的时候。

4.1 设计 AI 代理的集成点与提示工程

我们不能让 AI 漫无目的地生成代码。必须为它设计明确的“任务”和提供充足的“上下文”。以下是我设计的几个关键集成点:

  1. 填充服务层业务逻辑 :当代码生成器创建了一个空的 ProductService.cs (其中只有接口定义和空方法)后,AI 代理被触发。它的任务是:阅读 Product 实体属性、相关的 Category 实体、以及项目中原有的类似服务(如 OrderService )作为风格参考,然后为 CreateProductAsync UpdateProductAsync 等方法生成具体的实现,包括数据验证、业务规则检查(如“价格不能低于成本价”)、以及调用仓储层的代码。

  2. 生成复杂的验证属性或 Fluent Validation 规则 :虽然数据注解可以处理简单验证,但复杂规则(如“折扣开始日期必须早于结束日期”)更适合用 Fluent Validation。我们可以让 AI 根据实体属性的语义,自动生成对应的 AbstractValidator<Product> 类。

  3. 编写单元测试骨架 :AI 代理可以读取一个服务或控制器类,然后为其生成对应的 xUnit 或 NUnit 测试类骨架,包括常用的测试用例(如“当输入为空时应返回 BadRequest”)。

构建提示词(Prompt)是关键: 一个糟糕的提示词会得到糟糕的代码。你的提示词必须包含:

  • 角色设定 :“你是一个经验丰富的 .NET 后端开发专家,精通 ASP.NET Core 和领域驱动设计。”
  • 上下文 :提供当前文件的代码、相关实体类的代码、以及项目架构的简要说明(如“本项目采用分层架构,服务层调用仓储接口”)。
  • 具体任务 :指令必须清晰、无歧义。例如:“请为以下的 ProductService.CreateProductAsync 方法填充实现逻辑。要求:1. 验证输入 DTO 不为空;2. 检查产品名称是否已存在;3. 将 DTO 映射到 Product 实体;4. 设置创建时间和创建人;5. 调用 _productRepository.AddAsync 并保存;6. 返回创建成功的实体ID。”
  • 输出格式 :“只输出完整的 C# 方法代码,不要任何解释。”

4.2 实现自动化的 AI 代码注入流程

我们可以编写一个 Node.js 脚本 ai-code-enhancer.js 来实现这个流程:

const fs = require('fs').promises;
const path = require('path');
const { OpenAI } = require('openai'); // 假设使用 OpenAI API

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

async function enhanceServiceClass(filePath) {
    try {
        // 1. 读取目标文件内容
        const targetCode = await fs.readFile(filePath, 'utf-8');
        
        // 2. 读取相关的实体文件,构建上下文
        const entityPath = path.join(__dirname, '../Domain/Entities/Product.cs');
        const entityCode = await fs.readFile(entityPath, 'utf-8');
        
        // 3. 构建提示词
        const prompt = `
你是一个资深的 ASP.NET Core 开发专家。请基于以下上下文,为 ProductService 类中的空方法生成完整的业务逻辑实现。

项目架构:这是一个采用仓储模式和工作单元的三层架构项目。Service 层负责业务逻辑,调用 IRepository 进行数据持久化。

相关实体类代码:
\`\`\`csharp
${entityCode}
\`\`\`

需要实现的目标服务类代码(其中 // TODO: 标记的位置需要你填充):
\`\`\`csharp
${targetCode}
\`\`\`

请只输出完成填充后的整个 ProductService 类的完整 C# 代码,不要有任何额外的解释或注释。
        `;
        
        // 4. 调用 AI API
        const completion = await openai.chat.completions.create({
            model: "gpt-4",
            messages: [{ role: "user", content: prompt }],
            temperature: 0.2, // 低温度,确保生成结果稳定、确定性高
        });
        
        const generatedCode = completion.choices[0].message.content;
        
        // 5. (可选) 简单的代码格式清理,确保生成的是纯代码
        const cleanCode = generatedCode.replace(/```csharp|```/g, '').trim();
        
        // 6. 写回文件
        await fs.writeFile(filePath, cleanCode, 'utf-8');
        console.log(`Successfully enhanced: ${filePath}`);
        
    } catch (error) {
        console.error(`Error enhancing ${filePath}:`, error);
        // 错误处理:可以回退到原始文件或记录日志
    }
}

// 在生成管道中调用此函数
enhanceServiceClass('./Application/Services/ProductService.cs');

将这个脚本集成到之前的构建流水线中,在代码生成器执行完毕后自动运行,即可实现“生成-增强”的全自动化流程。

注意事项: AI 生成的代码必须经过严格的审查和测试!切勿盲目信任。应将此环节视为“高级代码补全”,开发者仍需对生成逻辑的业务正确性、安全性(如 SQL 注入)、性能负责。建议将 AI 生成的代码纳入常规的代码审查和单元测试流程。

5. 实战演练:生成一个完整的“订单管理”模块

让我们通过一个具体的例子,将上述所有步骤串联起来。假设我们要为一个电商系统添加“订单管理”功能。

5.1 定义领域模型 ( order.model.yaml ):

entities:
  - name: Order
    properties:
      - name: Id
        type: guid
        isKey: true
      - name: OrderNumber
        type: string
        format: "ORD-{yyyyMMdd}-{seq}"
        isRequired: true
      - name: CustomerId
        type: guid
        foreignKey: User.Id
        isRequired: true
      - name: OrderDate
        type: datetime
        isRequired: true
      - name: Status
        type: enum
        values: [Draft, Confirmed, Processing, Shipped, Delivered, Cancelled]
        defaultValue: Draft
      - name: TotalAmount
        type: decimal
        precision: 18
        scale: 2
    collections:
      - name: OrderItems
        entity: OrderItem
        relationship: OneToMany

  - name: OrderItem
    properties:
      - name: Id
        type: guid
        isKey: true
      - name: OrderId
        type: guid
        foreignKey: Order.Id
        isRequired: true
      - name: ProductId
        type: guid
        foreignKey: Product.Id
        isRequired: true
      - name: Quantity
        type: int
        minValue: 1
        isRequired: true
      - name: UnitPrice
        type: decimal
        precision: 18
        scale: 2
        isRequired: true
      - name: LineTotal
        type: decimal
        precision: 18
        scale: 2
        computed: "Quantity * UnitPrice"

5.2 执行自动化流水线:

  1. 模型解析与后端生成 :运行自定义工具,解析 order.model.yaml

    • T4 模板生成 Order.cs , OrderItem.cs , 并更新 AppDbContext
    • 同时,生成 OrderDto.cs , OrderItemDto.cs 等用于 API 传输的 DTO 类(可与实体类相同,或更简化)。
    • NSwag 进程检测到新的 DTO 类,运行并生成更新的 api-client.ts ,其中包含 OrderClient OrderItemClient 类以及它们的 TypeScript 接口。
  2. 前端模块脚手架 :在 Angular 项目中运行自定义 Schematic。

    ng generate my-schematics:crud-module --name=Order --hasDetail=true
    
    • 这会创建 src/app/features/order/ 目录,包含 order-list , order-detail 组件,以及路由配置。
    • 组件中已自动注入了 OrderClient ,列表组件模板中预置了显示订单号、日期、状态、总金额的表格。
  3. AI 业务逻辑增强 :后端生成器创建了空的 OrderService.cs OrderItemService.cs

    • AI 增强脚本被触发,读取这两个文件以及 Order OrderItem 实体。
    • 根据预设的提示词模板,AI 为 OrderService.CreateOrderAsync 生成复杂逻辑:验证客户存在、检查库存、计算订单总额(遍历 OrderItems 计算 LineTotal 并求和)、生成唯一的 OrderNumber 、设置初始状态为 Draft ,并开启一个数据库事务来保存订单和订单项。
    • 同时,为 OrderService.ConfirmOrderAsync 生成逻辑:检查订单状态是否为 Draft ,扣除库存,将状态更新为 Confirmed ,并可能触发一个“订单已确认”的领域事件。
  4. 生成验证规则 :AI 代理同时为 OrderDto 生成一个 OrderDtoValidator ,规则包括: OrderItems 列表不能为空,每个 OrderItem ProductId 必须有效, Quantity 必须大于0。

5.3 最终成果: 在几分钟内,我们获得了一个功能齐全的“订单管理”模块:

  • 后端 :具备完整领域模型、数据库上下文、包含复杂业务逻辑的服务层、以及一套完整的 RESTful API 控制器。
  • 前端 :具备类型安全的 Angular 服务、列表和详情视图组件、以及配置好的路由。
  • 开发者接下来只需要专注于 UI/UX 的细化、添加更特殊的业务规则,或者集成支付、物流等外部服务。

6. 常见问题、调试技巧与优化策略

在实际落地这套自动化工作流的过程中,你肯定会遇到各种问题。以下是我踩过坑后总结出的经验。

6.1 代码生成器的常见陷阱与排查

问题1:生成的代码存在编译错误。

  • 原因 :模板逻辑有缺陷,或者领域模型定义存在歧义(例如,类型映射错误)。
  • 排查 :不要一次性生成整个项目。先针对一个简单的实体(如 Category )进行测试生成。仔细检查生成的实体类、DbContext 和控制器。重点关注:
    • 命名空间引用是否正确。
    • 外键属性是否生成了正确的导航属性( virtual 关键字,正确的集合类型 ICollection<T> )。
    • 数据注解(如 [MaxLength] )的参数是否正确。
  • 技巧 :在 T4 模板或自定义工具中,加入大量的日志输出,记录每个生成步骤和决策,便于追踪错误源头。

问题2:NSwag 生成的 TypeScript 客户端模型与后端模型不对应。

  • 原因 :后端 DTO 类的属性使用了复杂的自定义类型或转换器,NSwag 的默认序列化设置无法正确处理。
  • 解决 :确保你的 DTO 是“平坦”的、可序列化的 POCO 对象。对于枚举,使用 [JsonConverter(typeof(JsonStringEnumConverter))] 确保生成的是字符串枚举。对于日期,统一使用 DateTimeOffset 。在 NSwag 配置中,可以指定 TypeNameGenerator PropertyNameGenerator 来统一前后端的命名风格。

问题3:Angular Schematic 生成的组件无法正确注入服务。

  • 原因 :Schematic 模板中导入路径错误,或者生成的服务类名与 API 客户端中的名称不匹配。
  • 排查 :首先检查生成的 *.component.ts 文件中的 import 语句和 constructor 注入语句。确保导入路径指向正确的 api-client.ts 文件位置。其次,检查 api-client.ts ,确认生成的客户端类名(如 OrderClient )是否与 Schematic 模板中硬编码的类名一致。 最佳实践是让 Schematic 动态解析 api-client.ts 文件来获取类名 ,而不是硬编码。

6.2 AI 代码代理的效能提升与质量控制

问题4:AI 生成的代码风格与项目现有代码不一致。

  • 原因 :提示词中缺乏足够的“风格上下文”。
  • 解决 :在提示词中附上 1-2 个项目中公认的、风格良好的核心服务或控制器文件作为示例。明确指示:“请严格遵循附例中的代码风格、命名约定(如异步方法以 Async 结尾)、日志记录方式(使用 _logger )和异常处理模式。”

问题5:AI 生成了不安全的或低效的代码(如 N+1 查询)。

  • 原因 :AI 基于通用训练数据生成,不了解你项目的具体架构和性能要求。
  • 解决 :在提示词中强化架构约束和最佳实践。例如:“在实现仓储调用时,请确保使用 _dbContext.Set<T>().Include(o => o.OrderItems).ThenInclude(i => i.Product) 来避免 N+1 查询问题。所有数据库操作都应在 Service 层开启的事务范围内进行。”
  • 必须的步骤 :建立对 AI 生成代码的 强制审查门禁 。可以将 AI 增强环节生成的代码放在一个特定的分支或目录,要求开发者必须进行人工审查、运行单元测试和集成测试后,才能合并到主开发分支。

问题6:API 调用成本与响应速度。

  • 原因 :每次生成都调用 AI API,对于大型项目或频繁生成,成本和时间可能成为问题。
  • 优化策略
    1. 缓存 :对相同的输入(领域模型哈希值 + 提示词模板)的生成结果进行缓存。只有模型或模板发生变化时才调用 AI。
    2. 批处理 :不要一个文件调用一次 API。将多个相关的空方法(如一个 Service 类的所有方法)组合在一个提示词中,让 AI 一次生成,减少调用次数。
    3. 使用更小的模型 :对于填充简单、模式固定的业务逻辑,可以尝试使用更便宜、更快的模型(如 GPT-3.5 Turbo),并在提示词中给予更严格的约束。

6.3 流程集成与团队协作考量

问题7:如何让团队接受并规范使用这套自动化流程?

  • 挑战 :开发者可能不信任生成的代码,或者习惯于自己手写。
  • 策略
    1. 教育 :向团队展示自动化生成一个完整模块的速度和一致性,突出其价值在于解放生产力,而非取代思考。
    2. 标准化 :将领域模型定义文件 ( .yaml ) 和代码生成流水线脚本纳入版本控制(如 Git)。任何新功能的开发,都必须从修改或添加领域模型定义开始。这强制了“设计先行”的优良习惯。
    3. 提供“逃生舱” :明确告知团队,生成的所有代码都是可以且应该被修改的。生成器负责 80% 的样板代码,剩下的 20% 复杂业务逻辑由开发者主导,AI 辅助。生成代码是起点,不是终点。

问题8:生成的代码如何应对业务逻辑的频繁变更?

  • 方案 :代码生成器不应该用于生成一次后就弃之不顾。当业务变更需要修改领域模型时,应首先更新权威的 domain.models.yaml 文件,然后重新运行整个生成流水线。
  • 关键 :生成器必须是 幂等 的(多次运行结果相同)和 非破坏性 的。对于已存在且被开发者修改过的文件(尤其是业务逻辑部分),生成器应该采用“合并”或“跳过”策略,而不是覆盖。通常的做法是:生成器只覆盖那些由它自己生成的文件(可以通过文件头部的特定注释标记来识别),对于标记为“已手动修改”的文件,则生成一个 .patch 文件或报告,由开发者决定如何合并变更。 我个人在实践中,会将 AI 增强步骤生成的内容与手动编写的代码物理分离。例如,AI 生成的代码放在 Service.AI.cs 部分类中,而开发者手动编写的扩展方法放在 Service.cs 中。这样在重新生成时,只需要替换 Service.AI.cs 文件即可。

更多推荐