Нормализация списка элементов в MSBuild - PullRequest
7 голосов
/ 12 декабря 2008

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

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

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

Ответы [ 3 ]

6 голосов
/ 26 июня 2013

Несмотря на то, что это старое решение, я никогда не мог заставить решение Thomas работать самостоятельно, но я нашел какой-то обходной путь, используя только встроенные команды с версией msbuild версии 4.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" />

Документация: Функции элемента

4 голосов
/ 23 декабря 2008

Пакет расширения 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>
2 голосов
/ 14 декабря 2008

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

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