如何在MSBuild属性中生成两个列表所有值的配对组合
在MSBuild中生成两个属性列表的所有组合值
假设你的MSBuild属性文件中有以下两个属性:
<Test1>foo1;foo2</Test1> <Test2>bar;baz</Test2>
你需要生成一个新属性Test,包含两个列表值的所有组合,最终格式如下:
<Test>foo1-bar;foo1-baz;foo2-bar;foo2-baz</Test>
虽然用C# Linq可以轻松实现,但MSBuild本身不支持Linq,不过可以利用它的项批处理特性来完成这个需求,具体实现如下:
完整实现代码
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <!-- 原始属性 --> <Test1>foo1;foo2</Test1> <Test2>bar;baz</Test2> </PropertyGroup> <!-- 把两个分号分隔的属性拆分为独立的项集合 --> <ItemGroup> <Test1Items Include="$(Test1)" /> <Test2Items Include="$(Test2)" /> </ItemGroup> <!-- 利用MSBuild交叉批处理生成所有组合项 --> <ItemGroup> <CombinedItems Include="%(Test1Items.Identity)-%(Test2Items.Identity)" /> </ItemGroup> <!-- 将组合项合并为分号分隔的目标属性 --> <PropertyGroup> <Test>@(CombinedItems, ';')</Test> </PropertyGroup> <!-- 可选:验证结果 --> <Target Name="PrintCombinedResult"> <Message Text="最终组合属性:$(Test)" Importance="high" /> </Target> </Project>
原理说明
- 拆分属性为项集合:通过
ItemGroup的Include属性,自动把分号分隔的字符串拆分成单个项,比如Test1会被拆成foo1和foo2两个独立的Test1Items项。 - 生成笛卡尔积组合:MSBuild的批处理机制中,当同时引用两个不同项集合的
Identity元数据时,会自动生成它们的所有可能组合(即笛卡尔积),这样就得到了foo1-bar、foo1-baz等所有组合项。 - 合并为属性:用
@(CombinedItems, ';')把组合项集合合并成分号分隔的字符串,赋值给Test属性。
简化写法
如果不需要保留拆分后的项集合,也可以直接一步生成组合项:
<ItemGroup> <CombinedItems Include="$([System.String]::Split('$(Test1)', ';'))-$([System.String]::Split('$(Test2)', ';'))" /> </ItemGroup>
这种写法利用MSBuild的内联函数直接拆分字符串,然后生成组合,结果和上面的完整写法一致。
内容的提问来源于stack exchange,提问作者Marcel V.
相关产品推荐
相关产品推荐

