是否可以在声明后修改ItemGroup的元数据.
例如:
<ItemGroup>
<SolutionToBuild Include="$(BuildProjectFolderPath)\MySolution.sln">
<Targets></Targets>
<Properties></Properties>
</SolutionToBuild>
</ItemGroup>
<Target Name="BuildNumberOverrideTarget">
<!--Code to get the version number from a file (removed)-->
<!--Begin Pseudo Code-->
<CodeToChangeItemGroupMetaData
ItemToChange="%(SolutionToBuild.Properties)"
Condition ="'%(SolutionToBuild.Identity)' ==
'$(BuildProjectFolderPath)\MySolution.sln'"
NewValue="Version=$(Version)" />
<!--End Pseudo Code-->
</Target>
Run Code Online (Sandbox Code Playgroud)
我希望有一种方法不要求我删除该项目然后重新声明它.
谢谢你的回答.Vaccano
Ale*_*lex 41
是的,您可以<ItemGroup>在定义后修改或添加元数据(MSBuild 3.5)
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Define ItemGroup -->
<ItemGroup>
<TestItemGroup Include="filename.txt">
<MyMetaData>Test meta data</MyMetaData>
</TestItemGroup>
<TestItemGroup Include="filename2.txt">
<MyMetaData>Untouched</MyMetaData>
</TestItemGroup>
</ItemGroup>
<Target Name="ModifyTestItemGroup" BeforeTargets="Build">
<!-- Show me-->
<Message Text="PRE: %(TestItemGroup.Identity) MyMetaData:%(TestItemGroup.MyMetaData) OtherMetaData:%(TestItemGroup.OtherMetaData)" Importance="high" />
<!-- Now change it - can only do it inside a target -->
<ItemGroup>
<TestItemGroup Condition="'%(TestItemGroup.MyMetaData)'=='Test meta data' AND 'AnotherCondition'=='AnotherCondition'">
<MyMetaData>Well adjusted</MyMetaData>
<OtherMetaData>New meta data</OtherMetaData>
</TestItemGroup>
</ItemGroup>
<!-- Show me the changes -->
<Message Text="POST: %(TestItemGroup.Identity) MyMetaData:%(TestItemGroup.MyMetaData) OtherMetaData:%(TestItemGroup.OtherMetaData)" Importance="high" />
</Target>
<Target Name="Build" />
</Project>
Run Code Online (Sandbox Code Playgroud)
参考:MSDN Library:操作项和属性的新方法(MSBuild)
有一种使用Update属性来修改元数据的新方法,例如
<ItemGroup>
<Compile Update="somefile.cs"> // or Update="*.designer.cs"
<MetadataKey>MetadataValue</MetadataKey>
</Compile>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
然而:
可选属性。(仅适用于 Visual Studio 2017 或更高版本中的 .NET Core 项目。)
更多内容请参见MSBuild 文档
我必须编写一个自定义任务来执行此操作:
下面是它的工作原理
<ItemGroup>
<ItemsToChange Include="@(SolutionToBuild)">
<Properties>ChangedValue</Properties>
</ItemsToChange>
<MetaDataToChange Include="Properties"/>
</ItemGroup>
<UpdateMetadata SourceList="@(SolutionToBuild)" ItemsToModify="@(ItemsToChange)" MetadataToModify="@(MetaDataToChange)">
<Output TaskParameter="NewList" ItemName="SolutionToBuildTemp" />
</UpdateMetadata>
<ItemGroup>
<SolutionToBuild Remove="@(SolutionToBuild)"/>
<SolutionToBuild Include ="@(SolutionToBuildTemp)"/>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
它使用更改后的值填充名为 SolutionToBuildTemp 的新项目。然后,我删除 SolutionToBuild 项中的所有内容,并使用 SolutionToBuildTemp 项填充它。
如果有人感兴趣的话,这里是该任务的代码(我也将其提交到 MSBuildExtenstionPack)。
// By Stephen Schaff (Vaccano).
// Free to use for your code. Need my Permission to Sell it.
using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace UpdateMetadata
{
///<summary>
/// Used to update the metadata in a ItemGroup (Note: Requires an MSBuild Call After using this task to complete the update. See Usage.)
/// Usage:
/// <?xml version="1.0" encoding="utf-8"?>
///<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Testing" ToolsVersion="3.5">
///
/// <!-- Do not edit this -->
/// <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets" />
/// <UsingTask AssemblyFile="C:\Base\Junk\UpdateMetadata\UpdateMetadata\bin\Debug\UpdateMetadata.dll" TaskName="UpdateMetadata"/>
///
///
/// <!--Re-setup the solutions to build definition-->
/// <ItemGroup>
/// <SolutionToBuild Include="$(BuildProjectFolderPath)\ChangeThisOne.sln">
/// <Properties>Change</Properties>
/// </SolutionToBuild>
/// <SolutionToBuild Include="$(BuildProjectFolderPath)\ChangeThisToo.sln">
/// <Properties>Change</Properties>
/// </SolutionToBuild>
/// <SolutionToBuild Include="$(BuildProjectFolderPath)\DontChangeThisOne.sln">
/// <Properties>Don'tChange</Properties>
/// </SolutionToBuild>
/// </ItemGroup>
///
/// <Target Name="Testing">
/// <Message Text="Before = %(SolutionToBuild.Identity) %(SolutionToBuild.Properties)" />
///
/// <ItemGroup>
/// <ItemsToChange Include="@(SolutionToBuild)">
/// <Properties>ChangedValue</Properties>
/// </ItemsToChange>
///
/// <ItemsToChange Remove="%(ItemsToChange.rootdir)%(ItemsToChange.directory)DontChangeThisOne%(ItemsToChange.extension)"/>
/// </ItemGroup>
///
/// <ItemGroup>
/// <MetaDataToChange Include="Properties"/>
/// </ItemGroup>
///
/// <UpdateMetadata SourceList="@(SolutionToBuild)" ItemsToModify="@(ItemsToChange)" MetadataToModify="@(MetaDataToChange)">
/// <Output TaskParameter="NewList" ItemName="SolutionToBuildTemp" />
/// </UpdateMetadata>
///
/// <ItemGroup>
/// <SolutionToBuild Remove="@(SolutionToBuild)"/>
/// <SolutionToBuild Include ="@(SolutionToBuildTemp)"/>
/// </ItemGroup>
///
/// <Message Text="After = %(SolutionToBuild.Identity) %(SolutionToBuild.Properties)"/>
/// </Target>
///</Project>
///</summary>
public class UpdateMetadata : Task
{
///<summary>
/// The list to modify.
///</summary>
[Required]
public ITaskItem[] SourceList { get; set; }
///<summary>
/// Items in <see cref="SourceList"/> to change the Metadata for.
/// It should have the valid metadata set.
///</summary>
[Required]
public ITaskItem[] ItemsToModify { get; set; }
///<summary>
/// List of metadata to modify. This is an item group, but any metadata in it is ignored.
///</summary>
public ITaskItem[] MetadataToModify { get; set; }
///<summary>
/// If true then info about the update is output
///</summary>
public Boolean OutputMessages { get; set; }
///<summary>
/// Changed List. If you call the following it can replace the <see cref="SourceList"/>:
///</summary>
[Output]
public ITaskItem[] NewList { get; set; }
///<summary>
/// Runs the task to output the updated version of the property
///</summary>
///<returns></returns>
public override bool Execute()
{
// If we got empty params then we are done.
if ((SourceList == null) || (ItemsToModify == null) || (MetadataToModify == null))
{
Log.LogMessage("One of the inputs to ModifyMetadata is Null!!!", null);
return false;
}
if (OutputMessages)
Log.LogMessage(MessageImportance.Low, "Beginning Metadata Changeover", null);
int sourceIndex = 0;
foreach (ITaskItem sourceItem in SourceList)
{
// Fill the new list with the source one
NewList = SourceList;
foreach (ITaskItem itemToModify in ItemsToModify)
{
// See if this is a match. If it is then change the metadat in the new list
if (sourceItem.ToString() == itemToModify.ToString())
{
foreach (ITaskItem metadataToModify in MetadataToModify)
{
try
{
if (OutputMessages)
Log.LogMessage(MessageImportance.Low, "Changing {0}.{1}",
NewList[sourceIndex].ToString(), metadataToModify.ToString());
// Try to change the metadata in the new list.
NewList[sourceIndex].SetMetadata(metadataToModify.ToString(),
itemToModify.GetMetadata(metadataToModify.ToString()));
}
catch (System.ArgumentException exception)
{
// We got some bad metadata (like a ":" or something).
Log.LogErrorFromException(exception);
return false;
}
}
}
}
sourceIndex += 1;
}
return true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我希望这对某些人有用,但代码显然是“使用风险自负”。
瓦卡诺
| 归档时间: |
|
| 查看次数: |
19287 次 |
| 最近记录: |