Как получить все ключи метаданных для любого элемента ItemGroup?

Есть ли способ получить все ключи метаданных, связанные с данным элементом?

Я хочу сделать что-то вроде следующего.

Данный:

  <ItemGroup>
    <MyItems Include="item1">
      <key1>val1</key1>
      <key2>val2</key2>
      <key3>val3</key3>
    </MyItems>
    <MyItems Include="item2">
      <key4>val4</key4>
    </MyItems>
  </ItemGroup>

Уметь определять, что у элемента item1 есть метаданные, доступные для ключа1, ключа2 и ключа3, и что у элемента2 есть метаданные, доступные для ключа4, не зная, каковы на самом деле имена этих ключей.

По сути, я пытаюсь использовать метаданные для указания атрибутов, о которых я понятия не имею, а затем пытаюсь найти способ проверить, какие атрибуты были указаны.

Иными словами, я считаю, что метаданные каждого элемента — это просто хэш, содержащий пары ключ/значение, и я пытаюсь выяснить, каковы все ключи.

Кто-нибудь знает, как это сделать с помощью msbuild?

Спасибо


person Zain Rizvi    schedule 04.07.2013    source источник
comment
Насколько я знаю, нет возможности перечислить метаданные элемента в MSBuild, но вы можете написать пользовательскую задачу BuildTask, которая перебирает отраженные метаданные, и может перечислить их.   -  person MikeR    schedule 15.07.2013
comment
Да, это был маршрут, по которому я пошел   -  person Zain Rizvi    schedule 27.07.2013


Ответы (1)


В итоге я решил это, используя пользовательскую встроенную задачу, подобную следующей:

<UsingTask
  TaskName="GetMetadataTask"
  TaskFactory="CodeTaskFactory"
  AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll" >
  <ParameterGroup>
    <MyItemGroup ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
    <MetadataString Output="true" />
  </ParameterGroup>
  <Task>
    <Using Namespace="System"/>
    <Code Type="Fragment" Language="cs">
      <![CDATA[
          StringBuilder command = new StringBuilder();
          foreach (ITaskItem item in MyItemGroup )
          {
              command.AppendFormat("ItemName={0}\r\n", item);
              foreach (string parameter in item.MetadataNames)
              {
                  command.AppendFormat("  {0}={1}\r\n", parameter, item.GetMetadata(parameter));
              }
              command.AppendFormat("\r\n");
          }
          MetadataString = command.ToString();
      ]]>
    </Code>
  </Task>
</UsingTask>

Обратите внимание, что приведенное выше также будет включать все метаданные по умолчанию, которые MSBuild автоматически добавляет к каждому элементу в группе элементов (например, FullPath, RootDir, Filename и т. д.). В моей реализации я добавил дополнительную проверку для игнорирования тех элементов метаданных, которые мне не нужны.

Пример использования:

<GetMetadataTask MyItemGroup="@(YourItemGroup)">
  <Output TaskParameter="MetadataString" PropertyName="YourMetadataString"/>
</GetMetadataTask>
<Message Text="$(YourMetadataString)" />

Чтобы увидеть вывод сообщения в окне вывода Visual Studio, вам может потребоваться изменить уровень детализации вывода MSBuild как минимум на "Нормальный".

person Zain Rizvi    schedule 26.07.2013
comment
Спасибо! Отличный сценарий! - person Sergey Kostrukov; 02.02.2015
comment
Не могли бы вы показать небольшой пример того, как использовать эту задачу? - person Ivan; 13.02.2015
comment
Спасибо, это действительно полезно! Я добавил пример кода для его вызова. - person EM0; 27.10.2015
comment
@EM, я пошел и нашел твое редактирование, которое было отклонено (ошибочно, ИМО). Вот для тех, кому @EM пытался помочь: <GetMetadataTask MyItemGroup="@(YourItemGroup)"> <Output TaskParameter="MetadataString" PropertyName="YourMetadataString"/> </GetMetadataTask> - person weir; 03.12.2015
comment
CodeTaskFactory не поддерживается в ядре dotnet, но по-прежнему работает с новой RoslynCodeTaskFactory от вношу пару изменений: TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" - person piedar; 06.03.2020
comment
Как заставить его работать для одного элемента? Синтаксис %(Item.Identity) не передает все метаданные. - person Denis535; 11.11.2020