Сравнение свойств и элементов
Свойства и элементы MSBuild применяются для передачи данных задачам, проверки условий и хранения значений, которые будут использоваться в файле проекта.
Свойства представляют собой пары имя-значение. Дополнительные сведения см. в разделе Свойства MSBuild.
Элементы — это объекты, которые обычно представляют файлы. Объекты элементов могут иметь сопоставленные коллекции метаданных. Метаданные представляют собой пары "имя — значение". Дополнительные сведения см. в разделе Элементы.
Скаляры и векторы
Поскольку свойства MSBuild являются парами "имя — значение" с одним строковым значением, они часто называются скалярами. Так как типы элементов MSBuild представляют собой списки элементов, они часто называются векторами. Однако на практике свойства могут представлять несколько значений, а в типах элементов может быть только один элемент или же элементы могут вовсе отсутствовать.
Внедрение зависимостей для целевого объекта
Чтобы проанализировать представление свойствами нескольких значений, рассмотрим общий принцип добавления целевого объекта в список целевых объектов, подлежащих сборке. Как правило, этот список представлен значением свойства, а имена целевых объектов разделены точкой с запятой.
<PropertyGroup>
<BuildDependsOn>
BeforeBuild;
CoreBuild;
AfterBuild
</BuildDependsOn>
</PropertyGroup>
Свойство BuildDependsOn
в основном используется в качестве аргумента атрибута DependsOnTargets
целевого объекта и эффективно его преобразует в список элементов. Это свойство можно переопределить, чтобы добавить целевой объект или изменить порядок выполнения целевых объектов. Например, примененная к объекту директива
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
CustomBuild;
</BuildDependsOn>
</PropertyGroup>
добавляет целевой объект CustomBuild в список целевых объектов, присваивая BuildDependsOn
значение BeforeBuild;CoreBuild;AfterBuild;CustomBuild
.
Начиная с MSBuild версии 4.0, внедрение зависимости для целевых объектов не рекомендуется. Используйте вместо него атрибуты AfterTargets
и BeforeTargets
. Дополнительные сведения см. в разделе Порядок сборки целевых объектов.
Преобразование между строками и списками элементов
MSBuild по мере необходимости осуществляет преобразование в типы элементов и строковые значения и наоборот. Чтобы проанализировать, как список элементов становится строковым значением, рассмотрим, что происходит, когда тип элемента используется в качестве значения свойства MSBuild.
<ItemGroup>
<OutputDir Include="KeyFiles\;Certificates\" />
</ItemGroup>
<PropertyGroup>
<OutputDirList>@(OutputDir)</OutputDirList>
</PropertyGroup>
Тип элемента OutputDir имеет атрибут Include
со значением "KeyFiles\;Certificates\". В результате синтаксического анализа из строки выделяются два элемента: KeyFiles\ и Certificates\. Если в качестве свойства OutputDirList используется тип элемента OutputDir, MSBuild преобразует или "выравнивает" тип элемента в строку с разделителем (точка с запятой): "KeyFiles\;Certificates\".
Свойства и элементы в задачах
Свойства и элементы используются в качестве входных и выходных данных для задач MSBuild. Дополнительные сведения см. в разделе Задачи.
Свойства передаются в задачи в виде атрибутов. В рамках задачи свойство MSBuild представлено типом свойства, значение которого можно преобразовать в строку и наоборот. Поддерживаемые типы свойства включают в себя bool
, char
, DateTime
, Decimal
, Double
, int
, string
, а также любой тип, который может обработать ChangeType.
Элементы передаются в задачи в виде объектов ITaskItem. В рамках задачи ItemSpec представляет значение элемента, а GetMetadata извлекает его метаданные.
Список элементов типа элементов можно передать в виде массива объектов ITaskItem
. Начиная с .NET Framework версии 3.5, элементы можно удалять из списка элементов в целевом объекте с помощью атрибута Remove
. Так как элементы можно удалить из списка элементов, тип элемента может не иметь элементов. Если список элементов передается в задачу, код в задаче должен проверить наличие такой возможности.
Порядок оценки свойств и элементов
На этапе оценки сборки импортированные файлы внедряются в сборку в порядке их расположения. Свойства и элементы определяются за три прохода в следующем порядке.
Свойства определяются и изменяются в порядке их расположения.
Определения элементов задаются и изменяются в порядке их расположения.
Элементы определяются и изменяются в порядке их расположения.
На этапе выполнения сборки свойства и элементы, определенные в рамках целевых объектов, оцениваются в отношении друг друга за один этап в порядке их расположения.
Однако это еще не все. Когда определены свойство, определение элемента или элемент, выполняется оценка его значения. Вычислитель выражений расширяет строку, в которой указано значение. Расширение строки зависит от этапа сборки. Ниже более подробно представлен порядок оценки свойств и элементов.
На этапе оценки сборки
Свойства определяются и изменяются в порядке их расположения. Выполняются функции свойства. В рамках выражений значения свойств в виде $(PropertyName) расширяются. Для расширенного выражения задается значение свойства.
Определения элементов задаются и изменяются в порядке их расположения. Функции свойств уже расширены в рамках выражений. Для расширенных выражений задаются значения метаданных.
Типы элементов определяются и изменяются в порядке их расположения. Значения элементов в формате @(ItemType) расширяются. Преобразования элементов также расширяются. Функции и значения свойств уже расширены в рамках выражений. Для расширенных выражений задаются значения списка элементов и метаданных.
На этапе выполнения сборки
- Свойства и элементы, определенные в рамках целевых объектов, оцениваются в отношении друг друга в порядке их расположения. Выполняются функции свойств, а значения свойств расширены в рамках выражений. Преобразования значений и элементов также расширяются. Для расширенных выражений задаются значения свойств, типа элементов и метаданных.
Слабые эффекты порядка оценки
На этапе оценки сборки оценке элементов предшествует оценка свойств. Несмотря на это, у свойств могут быть значения, которые зависят от значений элементов. Рассмотрим следующий сценарий.
<ItemGroup>
<KeyFile Include="KeyFile.cs">
<Version>1.0.0.3</Version>
</KeyFile>
</ItemGroup>
<PropertyGroup>
<KeyFileVersion>@(KeyFile->'%(Version)')</KeyFileVersion>
</PropertyGroup>
<Target Name="AfterBuild">
<Message Text="KeyFileVersion: $(KeyFileVersion)" />
</Target>
При выполнении задачи Message отображается следующее сообщение.
KeyFileVersion: 1.0.0.3
Это происходит, поскольку значением KeyFileVersion
фактически является строка "@(KeyFile->'%(Version)')". Элемент и преобразования элементов не были расширены при первом определении свойства, поэтому свойству KeyFileVersion
было присвоено значение нерасширенной строки.
На этапе выполнения сборки во время обработки задачи Message MSBuild расширяет строку "@(KeyFile->'%(Version)')", чтобы получилось "1.0.0.3".
Следует обратить внимание, что то же самое сообщение появится, даже если порядок групп свойств и элементов был изменен на обратный.
Во втором примере рассмотрим, что может произойти, когда группы свойств и элементов расположены в целевых объектах.
<Target Name="AfterBuild">
<PropertyGroup>
<KeyFileVersion>@(KeyFile->'%(Version)')</KeyFileVersion>
</PropertyGroup>
<ItemGroup>
<KeyFile Include="KeyFile.cs">
<Version>1.0.0.3</Version>
</KeyFile>
</ItemGroup>
<Message Text="KeyFileVersion: $(KeyFileVersion)" />
</Target>
При выполнении задачи Message отображается следующее сообщение.
KeyFileVersion:
Это происходит потому, что на этапе выполнения сборки группы свойств и элементов, определенные в рамках целевых объектов, одновременно оцениваются сверху вниз. Когда определено значение KeyFileVersion
, значение KeyFile
остается неизвестным. Поэтому при преобразовании элементов расширяется пустая строка.
В этом случае при изменении порядка групп свойств и элементов на обратный восстанавливается исходное сообщение.
<Target Name="AfterBuild">
<ItemGroup>
<KeyFile Include="KeyFile.cs">
<Version>1.0.0.3</Version>
</KeyFile>
</ItemGroup>
<PropertyGroup>
<KeyFileVersion>@(KeyFile->'%(Version)')</KeyFileVersion>
</PropertyGroup>
<Message Text="KeyFileVersion: $(KeyFileVersion)" />
</Target>
Значение KeyFileVersion
задано как "1.0.0.3", а не "@(KeyFile->'%(Version)')". При выполнении задачи Message отображается следующее сообщение.
KeyFileVersion: 1.0.0.3
См. также
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по