I had a good search on the Internet and could not find a way to do this. If anyone knows a clean inline way, please let me know. In the meantime, I wrote a simple task to complete this work. Usage is as follows:
<NormalizeByMetadata Items="@(ItemsToNormalize)" MetadataName="Filename"> <Output TaskParameter="NormalizedItems" ItemName="MyNormalizedItems"/> </NormalizeByMetadata>
After completing the above task, MyNormalizedItems will contain only those items from ItemsToNormalize that have a unique value for Filename metadata. If two or more elements have the same value for their Filename metadata, the first match will be included in the output.
MSBuild Task Code:
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(); } } }
Kent boogaart
source share