×

写给 .NET Core 开发者的 AI Prompt 工程:把需求说成可生成的代码

独孤求败 独孤求败 发表于2026-07-14 09:21:24 浏览8 评论0

抢沙发发表评论

AI 能写代码,但它不会自动知道你的项目边界、命名风格、异常策略、测试框架、数据库约定和架构规则。很多生成结果差,不是模型完全不行,而是 Prompt 只给了一个模糊任务:“帮我写一个 API”。

对 .NET Core 开发来说,一个有效 Prompt 应该像一份小型开发任务说明:上下文清楚、技术栈明确、边界具体、验收条件可验证。这样生成出来的代码才更接近项目真实需要。

差的 Prompt 为什么差

类似这样的请求很常见:

Create a user API in .NET Core.

它缺少所有关键约束:使用 Minimal API 还是 Controller?是否用 EF Core?数据库是什么?是否需要验证?返回什么错误格式?是否写测试?项目分层如何?AI 只能按默认猜测生成,结果往往看起来能运行,但很难直接进入项目。

好的 Prompt 要先给上下文

上下文不需要写成长篇文档,但要足够具体:

我在一个 ASP.NET Core 8 Web API 项目中新增用户注册功能。
项目使用 Controller + MediatR + FluentValidation + EF Core。
返回错误统一使用 ProblemDetails。
请只生成 Application 层 command、validator、handler,以及 Controller action。
不要生成数据库迁移。

这段话把技术栈、分层边界和不要做的事情都说清楚了。AI 最怕的不是任务难,而是边界模糊。

把架构规则写进 Prompt

如果你的项目有 Clean Architecture 约定,就不要只说“使用 Clean Architecture”。要写成具体规则:

架构约束:
1. Domain 层不能引用 EF Core。
2. Application 层只能依赖接口,不直接使用 DbContext。
3. Infrastructure 层实现仓储接口。
4. Controller 不写业务逻辑,只发送 MediatR command。
5. 所有公开 DTO 使用 record。

这样生成结果更容易保持引用方向正确。

让 AI 输出可编译的 C# 代码

Prompt 里最好明确文件边界。比如注册用户功能可以要求输出这些文件:

请按文件分段输出:
- RegisterUserCommand.cs
- RegisterUserValidator.cs
- RegisterUserHandler.cs
- UsersController.cs
- RegisterUserTests.cs

生成的核心 command 可以长这样:

public sealed record RegisterUserCommand(
    string Email,
    string Password,
    string DisplayName
) : IRequest<Result<Guid>>
;

public sealed class RegisterUserValidator : AbstractValidator<RegisterUserCommand>
{
    public RegisterUserValidator()
    {
        RuleFor(x => x.Email).NotEmpty().EmailAddress();
        RuleFor(x => x.Password).MinimumLength(12);
        RuleFor(x => x.DisplayName).NotEmpty().MaximumLength(80);
    }
}

这类输出比“一段完整代码”更容易复制到现有项目,也更容易逐文件审查。

明确错误处理策略

.NET 项目里错误处理风格差异很大:有人抛异常,有人返回 Result<T>,有人统一 ProblemDetails。Prompt 必须说明。

错误处理要求:
- 校验错误由 FluentValidation 产生。
- 业务冲突返回 Result.Conflict,不抛异常。
- Controller 将 Result 映射为 200、400、409。
- 不要返回裸字符串错误。

对应的 Controller 可以是:

[HttpPost("register")]
public async Task<IActionResult> Register(
    RegisterUserCommand command,
    CancellationToken cancellationToken
)

{
    var result = await sender.Send(command, cancellationToken);

    return result.Status switch
    {
        ResultStatus.Success => Ok(new { userId = result.Value }),
        ResultStatus.Conflict => Conflict(CreateProblem(result.Error)),
        ResultStatus.Invalid => ValidationProblem(result.ValidationErrors),
        _ => StatusCode(StatusCodes.Status500InternalServerError)
    };
}

Prompt 写得越清楚,AI 越不容易把异常、状态码和响应模型混成一团。

验收条件要可执行

只说“代码要好”没有意义。可以把验收标准写成测试要求:

请同时生成单元测试,至少覆盖:
1. 邮箱格式错误时验证失败。
2. 邮箱已存在时返回 Conflict。
3. 注册成功时返回新用户 ID。
4. handler 不直接引用 Controller 或 HttpContext。

测试示例:

[Fact]
public async Task Handle_ShouldReturnConflict_WhenEmailAlreadyExists()
{
    var repository = Substitute.For<IUserRepository>();
    repository.ExistsByEmailAsync("test@example.com", Arg.Any<CancellationToken>())
        .Returns(true);

    var handler = new RegisterUserHandler(repository);
    var command = new RegisterUserCommand("test@example.com""StrongPassword123!""Test");

    var result = await handler.Handle(command, CancellationToken.None);

    result.Status.Should().Be(ResultStatus.Conflict);
}

Prompt 也是团队工程资产

对个人来说,Prompt 可以临时写。对团队来说,常用 Prompt 应该像代码模板一样沉淀下来。比如“新增 CRUD 模块”“新增后台任务”“新增集成测试”“重构 Controller 到 Minimal API”,都可以形成固定格式。

好的 .NET Prompt 不追求华丽措辞,而是把真实工程约束告诉 AI:项目怎么分层、依赖怎么注入、错误怎么返回、测试怎么验证、哪些文件不能碰。越接近开发任务单,生成结果越可控。


群贤毕至

访客