You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MSBuild:如何动态包含生成的*.razor文件并完成编译

解决Razor文件生成后无法在单次构建中编译的问题

看起来你遇到的核心问题是MSBuild目标执行顺序错误:你的生成器在Razor组件编译的准备阶段之后才生成文件,导致MSBuild没把新生成的.razor文件纳入编译流程——只有重建时,因为会清理之前的构建状态、重新扫描所有文件,才能正确识别这些新文件。

下面是针对你的csproj的具体修复方案:

1. 调整生成与文件包含的顺序

当前你的CompileDocs目标依赖IncludeGeneratedFiles,但逻辑上应该先生成文件,再包含文件。同时要确保整个流程在Razor组件生成的关键阶段PrepareForRazorComponentGenerate之前完成。

修改CompileDocs和IncludeGeneratedFiles的定义:

<!--Execute the code generator first, then include generated files-->
<Target Name="CompileDocs" BeforeTargets="PrepareForRazorComponentGenerate">
  <Message Text="Generating Docs and Tests using $(RunCommand)" Importance="high"/>
  <Exec Command='$(RunCommand)' />
</Target>

<Target Name="IncludeGeneratedFiles" AfterTargets="CompileDocs" BeforeTargets="PrepareForRazorComponentGenerate" >
  <ItemGroup>
    <!-- 修正条件:只有文件存在时才包含(生成后才会加入编译) -->
    <Compile Include="Models\Snippets.generated.cs" Condition="Exists('Models\Snippets.generated.cs')" />
    <Compile Include="Models\DocStrings.generated.cs" Condition="Exists('Models\DocStrings.generated.cs')" />
    <!-- 强制重新扫描所有ExampleCode.razor文件,避免MSBuild缓存旧的文件列表 -->
    <RazorComponent Remove="**/*ExampleCode.razor" />
    <RazorComponent Include="**/*ExampleCode.razor" />
  </ItemGroup>
</Target>

修改说明:

  • 把CompileDocs的BeforeTargets改为PrepareForRazorComponentGenerate,确保生成文件在Razor编译准备之前完成。
  • IncludeGeneratedFiles改为在CompileDocs之后执行,这样生成的文件已经存在,能正确被包含。
  • 对RazorComponent先执行Remove再Include,强制MSBuild重新扫描文件,避免遗漏新生成的.razor文件。
  • 把Compile的条件从!Exists改为Exists,确保只有文件生成后才会加入编译流程。

2. 移除冗余的ExampleCode目标

你的ExampleCode目标逻辑和IncludeGeneratedFiles重复,而且条件!Exists('Models\DocStrings.generated.cs')会导致文件生成后反而不被包含,直接移除这个目标即可:

<!-- 移除这个冲突的目标 -->
<!--
<Target Name="ExampleCode" BeforeTargets="PrepareForRazorComponentGenerate" >
  <ItemGroup>
    <RazorComponent Include="**/*ExampleCode.razor" Condition="!Exists('Models\DocStrings.generated.cs')" />
    <Content Update="$(_RazorComponentInclude)">
      <Generator>MSBuild:RazorGenerateComponentDeclarationDesignTime</Generator>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </Content>
  </ItemGroup>
</Target>
-->

3. 简化BuildDependsOn配置

原来的BuildDependsOn把CompileDocs放在前面,但现在我们已经通过BeforeTargets精准控制了生成时机,可以简化这个配置避免冲突:

<PropertyGroup>
  <!-- 移除原来的BuildDependsOn配置,依赖关系已通过BeforeTargets控制 -->
  <!-- <BuildDependsOn>
    CompileDocs; $(BuildDependsOn)
  </BuildDependsOn> -->
</PropertyGroup>

验证修改效果

做完以上修改后,执行常规构建(无需重建):

  1. 生成器会先运行,生成.razor和.generated.cs文件
  2. MSBuild会重新扫描并包含这些新文件
  3. Razor编译器会为.razor文件生成对应的.g.cs文件,并编译进项目

这样就能实现生成与构建一步完成的需求。

内容的提问来源于stack exchange,提问作者mikes-so

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:23:55