CreateItem vs ItemGroup

Jak*_*ake 32 msbuild

在目标中创建项目有什么区别,如下所示:

<Target Name="DoStuff">
    <CreateItem Include="@(IntermediateAssembly)" >
        <Output TaskParameter="Include" ItemName="FileWrites"/>
    </CreateItem>
</Target>
Run Code Online (Sandbox Code Playgroud)

和这样:

<Target Name="DoStuff">
    <ItemGroup>
        <FileWrites Include="@(IntermediateAssembly)" />
    </ItemGroup>
</Target>
Run Code Online (Sandbox Code Playgroud)

你何时会使用其中一个,为什么?

Vac*_*ano 31

在3.5之前的MSBuild版本中,您无法定义目标内的属性或项目(如第二个示例中所示).所以改为使用了一个任务(CreateItem和CreateProperty)

如果您使用的是ToolsVersion 3.5,那么您不再需要使用CreateItem(如果您愿意,仍然可以使用).

最后,他们都创建相同的项目,具有相同的范围.使用第二种语法更具可读性,并且设置自定义元数据更容易(在我看来).

注意:3.5版本的MSBuild随.NET 3.5一起安装.虽然您需要ToolsVersion="3.5"ProjectMSBuild文件的标记中定义以使用3.5功能.

如果你想知道,我从Inside the Microsoft® Build Engine: Using MSBuild and Team Foundation Build我真正喜欢的书中得到了大部分这些信息(但我没有任何关联).

  • 我发现了一个很大的区别:CreateItem将通过转换操作(如<CreateItem Include ="@(SomeGroup->'%(SomeWildcardMetadata)')">扩展Include中给它的通配符,而ItemGroup声明不会扩展它. (7认同)
  • 是的,那本书很棒,我喜欢它:) :) :)感谢rec. (2认同)

小智 17

CreateItem和CreateProperty在MSBuild 3.5中已经过时(当然,它将始终继续工作).很明显,我们需要ItemGroup和PropertyGroup使用相同的熟悉语法才能在目标内部工作.

但是目标中的ItemGroup具有一些特殊的额外功能.它可以修改项目:例如,这将向Resources列表中的所有项添加true,这些项具有名为Primary的元数据,其值为true; 只有当没有复制元数据时:

<ItemGroup>
  <Resources Condition=" '%(Primary)' == 'true' ">
    <Copy Condition=" '%(Copy)' == '' ">true</Copy>
  </Resources>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

另一个神奇的力量:你现在可以从列表中删除项目.此示例将从"资源"列表中删除具有元数据类型值Bitmap的所有项目:

<ItemGroup>
  <Resources Condition=" '%(Type)'=='Bitmap' " Remove="@(Resources)"/>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

这些神奇的力量目前只在内部工作,而不是在外面.

有关这些内容的详细信息,我强烈推荐Sayed Hashimi关于MSBuild的书.它很容易在亚马逊上找到.

丹 - msbuild团队.


Ada*_*dam 8

我不认为接受的答案已经定义了差异.

不同之处是:

  • ItemGroup 在加载MSBuild脚本时进行评估.
  • CreateItem 执行目标时进行评估

这可能会导致脚本中的Item的值不同.

以一个任务为例,该任务对目录中与"*.txt"匹配的所有文件执行某些操作.如果在Visual Studio中加载了MSBuild脚本,则只有使用ItemGroup时,VS启动时才存在的文件将位于Item中.

如果您使用CreateItem - 它将在执行目标时搜索所有*.txt文件.

  • 提问者表示两者都是从目标内部召唤的.从你的答案来看,看起来你正在思考MSBuild 3.5之前的术语.(当ItemGroup无法放置在目标内时).如果ItemGroup在目标内,它就像通过CreateItem声明它一样动态.(即在目标运行时对其进行评估.)(参见"Microsoft Build Engine内部:使用MSBuild和Team Foundation Build"的第51页作为参考(或者只是尝试一下)). (10认同)