dotnet-template-engine 实战:用 Template Comparison 技能对 dotnet new 模板做并排对比与选型决策
【免费下载链接】skillsRepository for skills to assist AI coding agents with .NET and C#项目地址: https://gitcode.com/GitHub_Trending/skills17/skills
dotnet new提供了数十种项目模板,而webapi与webapp、blazor与blazorwasm、worker与console这类"看起来很像"的模板常常让开发者难以抉择。本仓库dotnet-template-engine插件中的template-comparison技能(定义于 SKILL.md)专门解决这个问题:它引导 AI Agent 逐个检查待选模板的真实参数与特性支持,产出并排对比表,并以一条决定性推荐收尾。读完本文,你将掌握这套"证据契约 + 决策契约"的对比方法论、常用模板对的选型捷径,以及如何将其与模板发现、项目创建等其他技能衔接成完整工作流。
技能定位:何时用、何时不用
template-comparison是 dotnet-template-engine 插件六个模板技能中的一环(其余为template-discovery、template-instantiation、template-smart-defaults、template-authoring、template-validation)。插件在 plugin.json 中声明其能力为"发现与搜索模板、检查模板参数与目标框架(net8.0/net9.0/net10.0)、脚手架解决方案、创作与验证自定义模板、从 NuGet 安装模板包",而对比选型正是其中承上启下的一环。
When to Use(何时使用)
- 用户正在几个相似模板之间做决定(例如
webapivswebapp、blazorvsblazorwasm、consolevsworker); - 用户问"我应该用哪个模板做 X?";
- 用户在创建项目之前,想先理解两个或多个模板之间的差异。
When Not to Use(何时不用)
- 用户想创建项目——应路由到
template-instantiation技能; - 用户想创作或验证自定义模板——应路由到
template-authoring或template-validation技能; - 用户只需要查找或检查单个模板——应路由到
template-discovery技能。
在 template-engine.agent.md 的 Triage and Routing 表中,这一路由关系被固化下来:"Compare templates X vs Y / which template should I use" 直接映射到template-comparison技能,避免 Agent 用创建流程去回答选型问题。
输入定义
| 输入 | 是否必需 | 说明 |
|---|---|---|
| 模板短名称(Template short names) | 是 | 两个或更多待对比的模板短名称(如webapi、webapp) |
| 对比焦点(Comparison focus) | 否 | 可选的侧重维度(如 auth、AOT、框架、交互性 interactivity) |
对比焦点是可选参数,但它决定了 Step 2 中对比表的"决策维度"——技能要求围绕用户声明的决策来组织表格,而不是堆一个无差别的超大表格。
工作流总览:两份核心契约
整个对比流程建立在一个三层结构中,其中前两层是这份技能的"灵魂":
- 证据契约(Evidence contract):并排对比表只有在"每个选项声明都基于当前已安装模板"时才有价值。因此每个
--help调用必须逐个顺序执行,为每个模板捕获相同的请求维度;对不可用的选项要标注为Not exposed,而不是猜测或从另一个模板借用标志。 - 决策契约(Decision contract):对比要围绕用户的实际决策优化,而不是追求表格体积。要覆盖每个请求维度、省略无关选项行、给出针对场景的理由,并在推荐起点可执行时附带一条安全的
--dry-run命令。
第三层则是具体的三个执行步骤:检查模板(Inspect)→ 构建对比表(Build the comparison table)→ 给出推荐(Recommend)。
Step 1:逐个检查每个模板
对每个待对比模板运行dotnet new <template> --help,收集其参数(名称、类型、默认值、选项 choices)以及支持的框架:
dotnet new webapi --help dotnet new webapp --help如果某个模板未安装,先搜索其提供方(provider)并报告缺失的前提条件;只有用户明确要求修改环境或同意安装时才执行安装——对比技能本身不改变环境。
为什么必须顺序执行 --help
--help调用必须顺序执行。模板引擎使用全局互斥锁(global mutex),并发运行多个dotnet new <template> --help命令会以瞬时的 "mutex"/"persistence" 错误和空输出失败。请一次只检查一个模板;若调用失败,重试一次再继续,并仍然基于你已有的参数知识产出对比,而不是以无答案结束。
这一约束在仓库中反复出现:template-discovery的 SKILL.md 与template-comparison的 SKILL.md 都明确写出同样的警告("fire severaldotnet new <template> --help/--dry-runcalls concurrently can produce a transient mutex/persistence error")。这是 .NET Template Engine 实际运行时的已知特性,也是本技能要求"一次只跑一条命令"的底层原因。对于 Agent 而言,这是影响执行编排的重要实操细节——并发调用不仅是风格问题,而是会真实导致空输出的事故源。
模板未安装时的处理
未安装的模板分为两类情况:
- SDK 自带模板:如
console、classlib等,无需安装,直接可用; - 需要 workload 或模板包的模板:如
maui、winui3、aspire-starter、func、orleans通常需要dotnet workload install <id>和/或dotnet new install <package>。如果短名称没有出现在dotnet new list中,应先用dotnet new list/dotnet new search定位正确的模板及其提供包,再决定是否推荐。
这一规则与template-discovery技能中的意图映射表相互印证:该表覆盖了webapi/webapp/mvc/blazor/blazorwasm/grpc/worker/console/xunit/nunit/mstest等常用模板,但明确指出maui、winui3、aspire、func、orleans等通常不在默认 SDK 安装中。
Step 2:构建并排对比表
对比表需要覆盖四个维度:
- 参数(Parameters)——名称、类型、默认值、选项 choices;
- 特性支持(Feature support)——auth、AOT、Docker、controllers、interactivity;
- 可用框架(Available frameworks)——如 net8.0、net9.0、net10.0;
- 分类(Classifications)——模板宣传的类别(Web、API、Blazor 等)。
技能明确要求:每个请求的决策维度一行,并在单元格中引用观察到的选项名;当某行专门问"模板生成什么、暴露什么"时,不得用泛泛的框架知识填充。
标准对比表示例
技能给出了如下示例形状:
| Aspect | webapi | webapp |
|---|---|---|
Auth(--auth) | None, Individual, SingleOrg, Windows | None, Individual, SingleOrg, ... |
AOT(--aot标志) | 若dotnet new webapi --help列出--aot则为 present | 若dotnet new webapp --help列出--aot则为 present |
Controllers(--use-controllers) | Yes | n/a |
| Interactivity | n/a | n/a |
| Frameworks | net8.0 / net9.0 / net10.0 | net8.0 / net9.0 / net10.0 |
| Classifications | Web, WebAPI | Web, Razor Pages |
注意示例中的严谨写法:AOT 一行的取值不是猜测,而是"若--help列出则为 present"的条件判断;Controllers 一行的n/a表示该模板不暴露此选项。这正是证据契约的体现——每个单元格都必须能回溯到某次--help输出。
对比"生成的依赖"(Generated Dependencies)
--help和--dry-run不会揭示包引用(package references)。当用户在不允许创建项目的前提下询问"生成的依赖"时,技能要求:检查已安装模板包内的源.csproj文件。同时明确禁止两件事——不得仅仅为了检查而创建临时项目,也不得猜测当前的包 ID 或测试平台默认值。
这一条在评测场景中格外重要:tests 目录下的 eval.yaml 中,"Select a test project template for an enterprise suite" 用例要求对比xunit、nunit、mstest三个模板的生成依赖、默认测试平台集成和框架选项,且明确"don't create projects"。这正是依赖源.csproj检查路径的典型应用。
Step 3:给出决定性推荐
对比必须以一条果断的Recommendation行收尾——绝不能让用户只拿到一张表。推荐格式为:
Recommendation:
<template>— 用一句话把选择与用户陈述的场景绑定。(若满足<condition>则选另一个。)
然后链接到template-instantiation技能去真正创建项目。技能强调:一份没有点名赢家(或没有明确"取决于 X")的对比是不完整的——正是这种犹豫不决,会让该技能与一条普通回答毫无差别。
给推荐配上可执行的下一步
当推荐起点可执行时,附上一条安全的--dry-run命令,让推荐落地为行动:
dotnet new webapi --name MyApi --framework net10.0 --dry-run这与template-instantiation技能的 Step 3 一致:该技能同样用--dry-run向用户展示将创建的文件,确认后再真正创建。两者的衔接路径为:template-comparison负责"选哪个",template-instantiation负责"怎么建"。
常见模板对的决策捷径
技能为四组高频对比对提供了仅用于推荐环节的默认选择(注意:捷径不能替代--help证据,填写对比表前仍需逐个检查):
| 对比对 | 默认选择 | 理由 |
|---|---|---|
webapivswebapp | JSON/REST 后端选webapi;服务端渲染的 HTML/Razor Pages 选webapp | webapi 自带 controllers/minimal APIs + OpenAPI,无 UI |
blazorvsblazorwasm | 需要离线/无服务器时选blazorwasm;需要灵活的服务器 + 客户端交互时选blazor(Web App) | 独立 WASM 完全客户端运行,可离线工作 |
workervsconsole | 长生命周期/队列/后台处理选worker | Generic Host 提供 DI、日志、配置、优雅停机、IHostedService生命周期 |
mvcvswebapp | 页面型应用选webapp(Razor Pages);规模化后需要 controller/view 分离选mvc | Razor Pages 对 CRUD 型页面更轻量 |
覆盖约束(Overrides)
以下约束优先于上表捷径:
- 当用户明确预期大型应用或共享 controller 逻辑时选
mvc——即使初期页面以 CRUD 为主; - 当富交互表单是核心、但又要求首次响应就到达有用 HTML 时,选带 Server 交互性的
blazor而非webapp。需要解释:首屏渲染由服务端完成,交互组件使用 Blazor 表单/组件模型而非 Razor Pages 的PageModel; - 需要离线支持时选
blazorwasm,并解释 PWA/service-worker 要求、首次加载后缓存的行为、以及执行不需要常驻在线服务器的事实; - 需要持久化队列处理器时选
worker,并把决策绑定到 Generic Host 生命周期、依赖注入、配置、日志、优雅停机以及真实持久化队列(而非内存循环)上。
这些捷径的评判逻辑与评测脚本的 rubric 高度一致:eval.yaml 中 "Choose between blazor and blazorwasm" 用例要求解释 "hosting/interactivity trade-offs (server-rendered vs WebAssembly)" 并把离线需求连接到具体推荐;"Decide which template fits a background processing scenario" 用例则要求用 "hosted service lifecycle" 解释 worker 模板为何适合长生命周期队列处理。
验证清单
技能自带的 Validation 清单(也是评测 rubric 的直接来源):
- 每个请求的模板都通过
dotnet new <template> --help检查过 - 对比覆盖了参数、特性支持、框架和分类四个维度
- 与用户场景相关的差异被显式点出
- 给出了推荐(或明确的权衡)
- 不支持或不存在的选项被标注,而非猜测
- 最终推荐是单条决定性的
Recommendation:行
对照 eval.yaml 中的 7 个评测用例,可以清晰看到这条清单如何被机械地验证:
- "Compare webapi vs webapp side by side" 用
output-matches正则要求输出同时出现webapi、webapp、auth、aot、docker、controllers、recommend关键词,且 rubric 明确要求"并排对比表而非两张独立列表"、"覆盖参数、特性支持(auth/AOT/Docker/controllers)和框架"; - "Choose MVC or Razor Pages for an admin portal" 用
\|.*\|正则强制要求输出包含 Markdown 表格行,从测试层面把"必须产出表格"固化为硬性标准; - 每个用例都带有
expect_tools: [skill]约束,即评测时要求 Agent 实际调用 skill 工具而非凭记忆作答。
常见陷阱
| 陷阱 | 解决方案 |
|---|---|
| 凭记忆对比未安装的模板 | 安装并逐个检查每个模板,让对比反映真实参数与选项 |
| 假设特性对等(Assuming feature parity) | 参数名和特性支持因模板而异——每个模板都用--help确认 |
| 对比根本不同类型的模板 | 只对比解决重叠问题的模板;目标场景不同时要明确指出 |
这三条陷阱从反面印证了证据契约的强制力。template-discovery技能中有一句同样的话值得记住:"Report a flag only when the current template's--helpoutput contains it"(只有当当前模板的--help输出中出现该标志时才报告它)——worker模板的 Windows 服务支持、某个模板是否有--aot标志,都必须以实际输出为准,绝不能从其他 SDK 或模板"借用"标志。
与仓库其他技能的协作闭环
template-comparison并非孤立技能,它与同插件的其他技能形成完整选型→创建闭环:
- 意图解析:用户说"我想要一个带认证的 Web API"时,
template-discovery的意图映射表(SKILL.md 中的 Intent → template short name 与 Keyword → parameter 两张表)把它解析为webapi+--auth Individual; - 对比选型:当候选不止一个(如
webapivswebapp、blazorvswebapp)时,template-comparison用本文的流程产出对比表与推荐; - 智能默认值:创建时若
--aot与--framework等跨参数存在隐含关系,template-smart-defaults(SKILL.md)只填补未设置的参数、绝不覆盖用户显式值; - 项目创建:最终由
template-instantiation(SKILL.md)执行创建,并负责 CPM(Directory.Packages.props)适配、--no-restore时序控制与dotnet build验证。
在 template-engine.agent.md 的技能清单(Skills Inventory)中,这六个技能被统一登记,而 agent 的分诊表(Triage and Routing)正是依据用户意图在它们之间做第一层路由。对于本文的对比主题,路由规则很简单:任何 "Compare templates X vs Y" 或 "which template should I use" 的请求,都会落到template-comparison。
小结
template-comparison的价值在于把"模板选型"从凭印象的问答升级为可验证的工程流程:先以--help逐个取证(证据契约),再按用户的决策维度组织并排表格,最后以一条Recommendation:行给出果断结论并衔接创建步骤。其核心实操要点可归纳为三条:
- 证据优先:一切参数、特性、框架声明都必须来自当前安装模板的
--help输出;缺失的选项标Not exposed,绝不猜测; - 顺序执行:模板引擎的全局互斥锁决定了
dotnet new系列命令必须串行调用,失败重试一次后仍要基于已有知识给出答案; - 果断收尾:对比表只是手段,决定性的推荐(或明确的权衡)才是交付物,并附上可执行的
--dry-run命令与template-instantiation的下一步入口。
当你下次在两个相似模板之间犹豫时,不妨把这份方法论交给 Agent:让每个单元格都源于一次真实的--help输出,让最终选择绑定到你的具体场景——这样的选型,既经得起评测脚本的 regex 校验,也经得起实际项目的考验。
【免费下载链接】skillsRepository for skills to assist AI coding agents with .NET and C#项目地址: https://gitcode.com/GitHub_Trending/skills17/skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考