在MSBuild中交叉连接ItemGroups

6

假设有以下内容..

 <?xml version="1.0" encoding="utf-8"?>
    <Project DefaultTargets="test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
        <ItemGroup>
            <ConfigFiles Include="*.config" />

            <DatabaseConfig Include="ABC">
                <Database>DB1</Database>
                <CsString>Database</CsString>
            </DatabaseConfig>

            <DatabaseConfig Include="DEF">
                <Database>DB2</Database>
                <CsString>Logging</CsString>
            </DatabaseConfig>
        </ItemGroup>


        <Target Name="test" >
            <!-- Some sort of join here (or somewhere)... -->
         <Message Text=" %(Combined.ConfigFile) %(Combined.Database) " />
        </Target> 
    </Project>

我希望输出结果像这样(假设有两个文件:one.config和two.config)。
one.config DB1
two.config DB1
one.config DB2
two.config DB2

(顺序不重要,只需两个ItemGroups的完整笛卡尔积)

2个回答

6
这似乎是一个简洁的解决方案:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <ItemGroup>
        <ConfigFiles Include="*.config" />

        <DatabaseConfig Include="ABC">
            <Database>DB1</Database>
            <CsString>Database</CsString>
        </DatabaseConfig>

        <DatabaseConfig Include="DEF">
            <Database>DB2</Database>
            <CsString>Logging</CsString>
        </DatabaseConfig>
    </ItemGroup>

    <Target Name="test" >
        <ItemGroup>
            <Combined Include="@(DatabaseConfig)">
                <ConfigFile>%(ConfigFiles.Identity)</ConfigFile>
            </Combined> 
        </ItemGroup>
    <Message Text=" %(Combined.ConfigFile) %(Combined.Database) " />
    </Target> 
</Project>

这种方法无法按照您的要求合并项目元数据或生成所需的输出。它只会在一行上输出“DB1”,在另一行上输出“DB2”。我建议的答案可以在组合元数据时提供灵活性,并且将产生您要求的输出。 - Michael
1
啊,我明白了,当我在本地尝试时出了什么问题:我认为我的示例配置文件路径是错误的。你的提供了完整的配置文件路径,而不仅仅是配置文件名/扩展名。 - Michael
哈哈哈,终究还是你的回答更加简洁明了。;-) - Michael

4
有一种方法可以在最小程度更改现有示例代码的情况下完成此操作。您可以将“ConfigFiles”项和“DatabaseConfig”项的元数据组合成一个新的“组合”项,然后输出该“组合”项。
要组合元数据,请使用目标批处理,批处理目标每次运行一次以针对每个“DatabaseConfig”项。然后,您可以调用另一个目标来输出组合的元数据,以获得所描述的输出。请查看我对示例代码的扩展,了解如何完成所有这些操作:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="test" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <ItemGroup>
    <ConfigFiles Include="*.config" />

    <DatabaseConfig Include="ABC">
      <Database>DB1</Database>
      <CsString>Database</CsString>
    </DatabaseConfig>

    <DatabaseConfig Include="DEF">
      <Database>DB2</Database>
      <CsString>Logging</CsString>
    </DatabaseConfig>
  </ItemGroup>

  <Target Name="test" DependsOnTargets="test_setup;test_output" >
    <!-- Logic here runs after targets listed in "DependsOnTargets". -->
  </Target>

  <!-- This will run once for each "DatabaseConfig" item. -->
  <Target Name="test_setup" Outputs="%(DatabaseConfig.Identity)">
    <PropertyGroup>
      <!-- Specify the Database for the current DatabaseConfig item -->
      <CurrentDb>%(DatabaseConfig.Database)</CurrentDb>
    </PropertyGroup>
    <ItemGroup>
      <!-- Add a new CombinedOutput item with each run, combining metadata. -->
      <CombinedOutput Include=" %(ConfigFiles.FileName)%(ConfigFiles.Extension) $(CurrentDb) " />
    </ItemGroup>
  </Target>

  <Target Name="test_output">
    <!-- Output the combined metadata from the CombinedOutput items -->
    <Message Text=" %(CombinedOutput.Identity) " />
  </Target>

</Project>

在样例中发生了什么:
1. `test` 目标现在只是调用其他两个目标执行工作的方式:`test_setup` 和 `test_output`。 2. `test_setup` 目标被批处理,并创建新的 `CombinedOutput` 项目。 3. 在 `test_setup` 后调用 `test_output` 目标以输出 `CombinedOutput` 项目的元数据。
来自 `test_output` 的输出:
one.config DB1
two.config DB1
one.config DB2
two.config DB2

我应该更明确,我需要这两个变量是分开的。这条消息只是为了测试,实际变量将在XmlUpdate步骤中使用。 - Dog Ears
嗯,是的,提前知道那会很好。;-) 我的建议回答了你最初的标准,但并没有专注于保持这些变量分开。 - Michael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接