我在使用MSBuild编写脚本时遇到以下问题: 我使用两个元数据“metadata1”和“metadata2”创建一个默认项“itemA”,其中metadata2指的是metadata1。
当我稍后定义itemA并覆盖metadata1时,metadata2仍然包含metadata1的默认值。如何让metadata2引用“new”metadata1?
代码中的插图如下:
<ItemDefinitionGroup>
<itemA>
<Metadata1>default</Metadata1>
<Metadata2>%(itemA.Metadata1)</Metadata2>
</itemA>
</ItemDefinitionGroup>
<ItemGroup>
<itemA Include="first" >
<Metadata1>m_data1</Metadata1>
</itemA>
</ItemGroup>
但请看打印
<Message Text="itemA.Metadata1 = %(itemA.Metadata1)" />
<Message Text="itemA.Metadata2 = %(itemA.Metadata2)" />
提供了:
itemA.Metadata1 = m_data1 ***<-- correctly updated***
itemA.Metadata2 = default ***<-- why showing the default value, not* m_data1??**
如何使itemA.Metadata2在更新后与itemA.Metadata1具有相同的值?
答案 0 :(得分:1)
我认为这是不可能的,因为评估顺序为Item Definitions - Value Sources - Note:
ItemGroup中的项元数据在ItemDefinitionGroup元数据声明中没有用,因为ItemDefinitionGroup元素在ItemGroup元素之前处理。
您必须覆盖ItemGroup
中itemA的Metadata2值 <ItemDefinitionGroup>
<itemA>
<Metadata1>default</Metadata1>
<Metadata2>%(Metadata1)</Metadata2>
</itemA>
</ItemDefinitionGroup>
<ItemGroup>
<itemA Include="first" >
<Metadata1>m_data1</Metadata1>
<Metadata2>%(Metadata1)</Metadata2>
</itemA>
</ItemGroup>
答案 1 :(得分:1)
作为palo states,由于Metadata2已经过评估,因此您必须明确覆盖该值。您对Metadata1的更改不会自动传播到初始化期间引用它的其他位置。
但是,您可以通过启动MSBuild的新实例并将更新的元数据作为属性传递来“重新评估”项目的元数据。从命令行对此项目运行msbuild /t:Wrapper
将导致Metadata1和Metadata2打印相同的值:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DefaultMetadata1 Condition="DefaultMetadata1==''">default</DefaultMetadata1>
</PropertyGroup>
<ItemDefinitionGroup>
<itemA>
<Metadata1>$(DefaultMetadata1)</Metadata1>
<Metadata2>%(itemA.Metadata1)</Metadata2>
</itemA>
</ItemDefinitionGroup>
<ItemGroup>
<itemA Include="first" >
<Metadata1>m_data1</Metadata1>
</itemA>
</ItemGroup>
<Target Name="Wrapper">
<MSBuild
Projects="$(MSBuildProjectFile)"
Targets="Worker"
Properties="DefaultMetadata1=%(itemA.Metadata1)"
/>
</Target>
<Target Name="Worker">
<Message Text="itemA.Metadata1 = %(itemA.Metadata1)" />
<Message Text="itemA.Metadata2 = %(itemA.Metadata2)" />
</Target>
</Project>
这种方法的有用性取决于你想要完成的事情。毫无疑问,您可以使用属性而不是项元数据来查找备用解决方案。
虽然上述解决方案适用于您描述的案例,但它很快就会失控。可能有一个更简单的解决方案,可能涉及一些冗余代码。
我的建议是使用简单的解决方案,尽可能地消除尽可能多的冗余,而无需发明新方法来绕过MSBuild的小功能集。这里聪明的技巧可能不会在一天结束时为你节省很多LOC,并且可能导致代码不太可读,这使得新手更难理解正在发生的事情。