2008-12-12 6 views
6

Я пытаюсь получить список всех модульных тестовых сборок под корнем моего проекта. Я могу сделать это следующим образом:Нормализующий список элементов в MSBuild

<CreateItem Include="**\bin\**\*.UnitTest.*.dll"> 
    <Output TaskParameter="Include" ItemName="Items"/> 
</CreateItem> 

Однако, это будет найти те же библиотеки DLL несколько раз, так как они существуют в нескольких подкаталогов. Есть ли простой способ для меня нормализовать на основе метаданных элемента (то есть имя файла и расширение), чтобы получить список уникальных DLL-модулей с единичным тестированием? Или мне нужно прибегнуть к написанию моей собственной задачи?

ответ

4

MSBuild Extension Pack содержит задачу 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> 
+0

Звучит полезно - спасибо. Попробуй это в следующий раз, когда мне это понадобится. – 2009-08-24 09:17:35

2

У меня был хороший поиск в Интернете, и я не мог найти способ сделать это. Если кто-то знает чистый встроенный способ, пожалуйста, дайте мне знать. Тем временем я написал простую задачу, чтобы выполнить эту работу. Использование выглядит следующим образом:

<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(); 
     } 
    } 
} 
+0

Как создать единичный тест для задачи NormalizeByMetadata? – Kiquenet 2014-09-11 08:15:10

4

Несмотря на то, что это старый, я никогда не мог получить решение Томас работать сам, но я нашел своего рода обходной путь, используя только встроенные команды с v4.0 из MSBuild:

<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" />