如何通过MSBuild将其他文件夹的.g.cs文件与对应.cs文件分组?
如何通过MSBuild将Generated文件夹中的生成文件与对应非生成文件分组?
我有一个.NET 6项目,希望把“Generated”文件夹内的生成文件(如*.g.cs)和对应的非生成文件嵌套分组显示。核心需求是利用DependentUpon元素实现文件关联,但该元素仅对同目录文件生效,需要解决以下关键问题:
- 映射所有
Generated\**\*.g.cs文件到对应的*.cs文件 - 将
.g.cs文件复制到对应.cs文件的同级目录以支持分组 - 为关联的
.cs和.g.cs生成DependentUpon元素 - 排除原
Generated文件夹中的文件,避免重复编译
完整MSBuild配置
将以下配置添加到你的.csproj文件中:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0</TargetFramework> </PropertyGroup> <!-- 收集Generated文件夹下所有.g.cs文件 --> <ItemGroup> <GeneratedFiles Include="Generated\**\*.g.cs" /> </ItemGroup> <!-- 编译前将.g.cs复制到对应.cs文件的同级目录 --> <Target Name="CopyGeneratedFilesToSourceDir" BeforeTargets="BeforeCompile"> <Copy SourceFiles="@(GeneratedFiles)" DestinationFiles="$([System.String]::Copy('%(GeneratedFiles.FullPath)').Replace('Generated\', ''))" SkipUnchangedFiles="true" /> </Target> <!-- 配置文件关联与排除原文件 --> <ItemGroup> <!-- 为复制后的.g.cs添加DependentUpon关联,隐藏原Generated文件夹中的文件 --> <Compile Update="**\*.g.cs" Condition="Exists('%(RootDir)%(Directory)%(Filename.Substring(0, %(Filename.Length)-2)).cs')"> <DependentUpon>%(Filename.Substring(0, %(Filename.Length)-2)).cs</DependentUpon> <Visible>false</Visible> </Compile> <!-- 移除Generated文件夹中的文件,避免重复编译 --> <Compile Remove="Generated\**\*.g.cs" /> </ItemGroup> <!-- 清理时删除复制的.g.cs文件(可选) --> <Target Name="CleanGeneratedCopies" AfterTargets="Clean"> <Delete Files="$([System.String]::Copy('%(GeneratedFiles.FullPath)').Replace('Generated\', ''))" /> </Target> </Project>
配置说明
- 收集生成文件:用
<GeneratedFiles>项组统一管理所有Generated目录下的.g.cs文件,方便后续批量操作。 - 复制文件到目标目录:自定义
CopyGeneratedFilesToSourceDir目标在编译前执行,通过替换路径中的Generated\前缀,将生成文件复制到对应.cs文件的同级目录,SkipUnchangedFiles避免无意义的重复复制。 - 文件关联与排除:
- 更新
<Compile>项,通过截取文件名(去掉.g后缀)自动关联到对应的.cs文件,同时设置<Visible>false隐藏原Generated文件夹内的文件。 - 移除
Generated目录下的.g.cs文件,防止原文件和复制后的文件同时参与编译导致重复定义。
- 更新
- 可选清理步骤:
CleanGeneratedCopies目标会在执行dotnet clean或VS的清理命令时,删除复制到源目录的.g.cs文件,保持项目目录整洁。
测试验证
- 创建.NET 6控制台应用;
- 在项目根目录创建
Generated文件夹,添加Program.g.cs文件; - 将上述配置写入
.csproj文件; - 编写示例代码:
// Program.cs partial class Program { public static void Main() { Foo(); } } // Generated\Program.g.cs partial class Program { public static void Foo() => Console.WriteLine("Generated"); } - 重新加载项目,即可看到
Program.g.cs嵌套在Program.cs下方,原Generated文件夹会被隐藏(可通过“显示所有文件”开关查看,但不会参与编译)。
最终可实现生成文件与对应非生成文件嵌套显示,原Generated文件夹可被隐藏或清空,完全满足需求。
内容的提问来源于stack exchange,提问作者l33t
相关产品推荐
相关产品推荐

