Skip to content

Instantly share code, notes, and snippets.

@abombss
Created May 30, 2013 08:20
Show Gist options
  • Save abombss/5676461 to your computer and use it in GitHub Desktop.
Save abombss/5676461 to your computer and use it in GitHub Desktop.
MSBuild Join Items Task
<UsingTask
TaskName="JoinItems"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
<ParameterGroup>
<OuterItems ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<OuterProperty Required="false" ParameterType="System.String" />
<InnerItems ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<InnerProperty Required="false" ParameterType="System.String" />
<IgnoreCase Required="false" ParameterType="System.String" />
<CopyMetadata Required="false" ParameterType="System.String" />
<LeftOuterJoin Required="false" ParameterType="System.String" />
<NewTaskItems Required="false" ParameterType="System.String" />
<Items ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true" />
</ParameterGroup>
<Task>
<Using Namespace="System"/>
<Using Namespace="System.Linq"/>
<Using Namespace="System.Collections.Generic"/>
<Using Namespace="Microsoft.Build.Framework"/>
<Code Type="Fragment" Language="cs">
<![CDATA[
var xComparand = String.IsNullOrWhiteSpace(OuterProperty) ? "Identity" : OuterProperty;
var yComparand = String.IsNullOrWhiteSpace(InnerProperty) ? "Identity" : InnerProperty;
var comparer = Boolean.Parse( (IgnoreCase ?? "true") ) ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal;
var shouldCopyMetadata = Boolean.Parse( (CopyMetadata ?? "true") );
var performLeftOuterJoin = Boolean.Parse( (LeftOuterJoin ?? "false") );
var createNewTaskItems = Boolean.Parse( (NewTaskItems ?? "false") );
var qryInnerJoin = OuterItems.Join(
InnerItems,
x => x.GetMetadata(xComparand),
x => x.GetMetadata(yComparand),
(x, y) => new { Outer=x, Inner=y },
comparer);
var qryLeftOuterJoin = OuterItems.GroupJoin(
InnerItems,
x => x.GetMetadata(xComparand),
x => x.GetMetadata(yComparand),
(x, y) => new { Outer=x, Inner=y },
comparer)
.SelectMany(
x => x.Inner.DefaultIfEmpty(),
(x,y) => new { Outer=x.Outer, Inner=y });
var output = new List<ITaskItem>(Math.Max(OuterItems.Length, InnerItems.Length));
foreach (var joinedItem in (performLeftOuterJoin ? qryLeftOuterJoin : qryInnerJoin))
{
var newItem = (createNewTaskItems) ? (ITaskItem) new TaskItem(joinedItem.Outer.ItemSpec) : joinedItem.Outer;
if (shouldCopyMetadata && createNewTaskItems)
{
joinedItem.Outer.CopyMetadataTo(newItem);
}
if (shouldCopyMetadata && joinedItem.Inner != null)
{
joinedItem.Inner.CopyMetadataTo(newItem);
}
output.Add(newItem);
}
Items = output.ToArray();
]]>
</Code>
</Task>
</UsingTask>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment