如何使用MSBuild ItemGroup成员作为属性的单个项目?

时间:2011-03-02 19:41:28

标签: msbuild

所以我有点想在MSBuild中写作。

我喜欢在ItemGroups中存储东西的想法,因为它易于迭代,你可以拥有多个字段。

这使它们有点像一个类(更像是一个结构),但它们以一种感觉像lambda表达式的方式响应目标和任务的迭代语法。

但是我继续遇到我想要访问项目组中特定项目的值的情况,即,像访问属性一样访问它。

在这种情况下,我遇到了如何隔离组内单个项目的问题。

当项目组在目标或任务中进行批处理时,由于使用元数据名称进行寻址或使用公共项目组名称进行寻址,您可以使用“当前”项的值,即@(ItemsName)或% (MetaDataName)。

但我想做的事情是:使用Item组作为System.Configuration类,它包含配置文件的一部分中的条目值。因此,通常的做法是将ItemGroup命名为与配置文件中的节名称匹配。但是,ItemGroup不是可通过构建引擎接口访问的可寻址元素,只有项本身是可寻址的。

单独命名ItemGroup中的项目而不是将它们全部命名并使用Include或元数据字段来区分它们可能会很好。这使得它们的行为类似于属性,因为它们可以作为不同的项单独地寻址。因此您可以通过这种方式轻松地在条件中使用它们的值:'@(UniqueItemName->'%(Value)')。

然而,可迭代的功能基本上就丢失了。

为了缩小范围,假设我有一个配置文件,该文件通过和xml任务读入一个Item组,以便一个部分中的元素名称成为项目组中项目的名称和每个配置文件元素的属性是成为元数据的属性:

<configItemFlag name="displayDebugMessages" value="true" note="use with abandon" />
<configItemFlag name="displaySecurityValueMessages" value="false" note="use with caution" />

当我想在条件中测试它时,我需要将其缩小到类似的东西:

<Messge Text="Debug Message: you are debugging!" Condition="'@(configItemFlag->'%(Name)')' == 'displayDebugMessages' AND '@(configItemFlag->'%(Value)')' == 'true'/>

但这仅评估比较,并且通常不会评估为单个布尔值。

那么有没有什么方法可以通过语法将其归结为可靠的测试?

2 个答案:

答案 0 :(得分:3)

这是否适用于您要做的事情?

<ItemGroup>
  <ConfigItemFlag Include="displayDebugMessages">
    <Value>true</Value>
    <Note>use with abandon</Note>
  </ConfigItemFlag>
  <ConfigItemFlag Include="displaySecurityValueMessages">
    <Value>false</Value>
    <Note>use with caution</Note>
  </ConfigItemFlag>
</ItemGroup>

<Target Name="Build">
  <Message
    Condition="
      '%(ConfigItemFlag.Identity)' == 'displayDebugMessages' AND
      '%(Value)' == 'true'"
    Text="Debug Message: you are debugging, %(Note)!"
    /> 
</Target>

输出:

Build:
  Debug Message: you are debugging, use with abandon!

(对评论的回应)

...我唯一能够使用meta作为属性的东西并不是那么好,除非目标会在整个过程中大量使用它们。基本上,它涉及通过批量处理项目并为每个批次创建本地属性来将每个项目展平为属性。

<Target Name="BuildOne"
  Outputs="%(ConfigItemFlag.Identity)">
  <!-- flatten this batch to properties -->
  <PropertyGroup>
    <_Identity>%(ConfigItemFlag.Identity)</_Identity>
    <_Value>%(ConfigItemFlag.Value)</_Value>
    <_Note>%(ConfigItemFlag.Note)</_Note>
  </PropertyGroup>
  <!-- use meta as properties -->
  <Message
    Condition="
      '$(_Identity)' == 'displayDebugMessages' AND
      '$(_Value)' == 'true'"
    Text="Debug Message: you are debugging, $(_Note)!"
    /> 
</Target>
<Target Name="Build" DependsOnTargets="BuildOne"
  />

答案 1 :(得分:1)

您似乎遇到了msbuild脚本语言的一些限制。您是否考虑过编写自定义任务来执行您要查找的内容?这样,您就可以使用完整编程语言的全部功能来应对您想要执行的简单条件检查。