MSBuild에서 항목 목록을 정규화합니다
문제
프로젝트의 루트 아래에서 모든 단위 테스트 어셈블리 목록을 얻으려고 노력하고 있습니다. 다음과 같이 할 수 있습니다.
<CreateItem Include="**\bin\**\*.UnitTest.*.dll">
<Output TaskParameter="Include" ItemName="Items"/>
</CreateItem>
그러나 여러 하위 다이렉터에 존재하기 때문에 동일한 DLL을 여러 번 찾을 수 있습니다. 고유 한 단위 테스트 DLL 목록을 얻을 수 있도록 항목 메타 데이터 (예 : 파일 이름 및 확장자)를 기반으로 정규화하는 쉬운 방법이 있습니까? 아니면 내 자신의 과제를 작성해야합니까?
해결책
그만큼 MSBuild 확장 팩 작업을 포함합니다 MSBUILDHELPER, 명령을지지합니다 삭제 된 삭제.
<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>
다른 팁
이것이 오래 되었음에도 불구하고 Thomas Solution을 스스로 일할 수는 없었지만 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