MSBuild: ItemGroup Metadata Inversion

Sometimes it’s useful to treat a piece of metadata as though it were the actual item. This is particularly true if the metadata refers to a file location, so one could pull well-known metadata off the metadata value.

MSBuild does not support metadata having metadata. However, an “inversion” can be performed, where a new ItemGroup is created with the metadata as the primary item entry. The example below also places the original ItemGroup Identity as metadata on the new ItemGroup entries, creating a bidirectional mapping.

<Project ToolsVersion="3.5" xmlns="">
  <Import Project="$(MSBuildExtensionsPath)\ExtensionPack\MSBuild.ExtensionPack.tasks"/>
    <ProjectDefinitions Include="First">
    <ProjectDefinitions Include="Second">
    <ProjectDefinitions Include="Third">
  <Target Name="Default">
      <ProjectFiles Include="%(ProjectDefinitions.ProjectFile)">
    <Message Text=quot;Project files: @(ProjectFiles) (definitions: @(ProjectFiles->'%(ProjectDefinition)'))"/>
Project files: one.sln;two.sln;three.sln (definitions: First;Second;Third)

Note that you do have to watch your grouping; if the metadata being inverted is not unique for all entries in the original ItemGroup, then some entries in the resulting ItemGroup will have multi-valued metadata for their “original Identity” values.