MSBuildの中のアイテムのリストを正規化します
質問
私は私のプロジェクトのルートの下にあるすべてのユニットテストアセンブリのリストを取得しようとしています。次のように私はこれを行うことができます:
<CreateItem Include="**\bin\**\*.UnitTest.*.dll">
<Output TaskParameter="Include" ItemName="Items"/>
</CreateItem>
彼らは複数のサブディレクトリに存在するため、しかし、これは同じのDLLを複数回あります。私はユニークなユニットテストのDLLのリストを取得するように、私はアイテムのメタデータ(すなわち、ファイル名と拡張子)に基づいて正規化するための簡単な方法はありますか?それとも私は自分の仕事を書くことに頼らなければならないのですか?
解決
MSBuildの拡張パックには、コマンドをサポートする、のMSBuildHelper のタスクが含まれていますのRemoveDuplicateFiles の
<CreateItem Include="**\bin\**\*.UnitTest.*.dll">
<Output TaskParameter="Include" ItemName="Items"/>
</CreateItem>
<MSBuild.ExtensionPack.Framework.MsBuildHelper TaskAction="RemoveDuplicateFiles" InputItems1="@(Items)">
<Output TaskParameter="OutputItems" ItemName="Items"/>
</MSBuild.ExtensionPack.Framework.MsBuildHelper>
他のヒント
これは古いですが、私は自分自身を仕事にトーマス・ソリューションを取得することができませんでしたが、私はMSBuildののV4.0でのみ組み込みコマンドを使用して、ソートの回避策を見つけた:
<ItemGroup>
<TestAssemblies Include="$(SolutionRoot)\**\bin\*.Tests.dll" />
<TestItems Include="%(TestAssemblies.FileName)%(TestAssemblies.Extension)">
<ItemPath>%(TestAssemblies.Identity)</ItemPath>
</TestItems>
<DistinctTestItems Include="@(TestItems->Distinct())"></DistinctTestItems>
</ItemGroup>
<Message Text="%(DistinctTestItems.ItemPath)" Importance="high" />
ドキュメント:項目機能する
私はオンラインの良い検索を持っていたし、これを行うのいずれかの方法を見つけることができませんでした。誰でもきれいな組み込みの方法を知っているなら、私に知らせてください。一方で、私は仕事をするための簡単なタスクを書きました。使い方は次のようになります:
<NormalizeByMetadata Items="@(ItemsToNormalize)" MetadataName="Filename">
<Output TaskParameter="NormalizedItems" ItemName="MyNormalizedItems"/>
</NormalizeByMetadata>
上記のタスクが実行された後、、MyNormalizedItems
はItemsToNormalize
メタデータに一意の値を持つFilename
からの項目のみが含まれます。二つ以上の項目がそのFilename
メタデータの値が同じ場合は、最初の試合は、出力に含まれます。
のMSBuildタスクのためのコードがあります:
public class NormalizeByMetadata : Task
{
[Required]
public ITaskItem[] Items
{
get;
set;
}
[Required]
public string MetadataName
{
get;
set;
}
[Output]
public ITaskItem[] NormalizedItems
{
get;
private set;
}
public override bool Execute()
{
NormalizedItems = Items.Distinct(new ItemEqualityComparer(MetadataName)).ToArray();
return true;
}
private sealed class ItemEqualityComparer : IEqualityComparer<ITaskItem>
{
private readonly string _metadataName;
public ItemEqualityComparer(string metadataName)
{
Debug.Assert(metadataName != null);
_metadataName = metadataName;
}
public bool Equals(ITaskItem x, ITaskItem y)
{
if (x == null || y == null)
{
return x == y;
}
var xMetadata = x.GetMetadata(_metadataName);
var yMetadata = y.GetMetadata(_metadataName);
return string.Equals(xMetadata, yMetadata);
}
public int GetHashCode(ITaskItem obj)
{
if (obj == null)
{
return 0;
}
var objMetadata = obj.GetMetadata(_metadataName);
return objMetadata.GetHashCode();
}
}
}
所属していません StackOverflow