Использование функций элемента по значениям метаданных
Фон: Я управляю довольно большим решением. Каждый так часто люди добавляют ссылку на DLL в проект в решении, где они должны добавить ссылку на проект. В таком случае я хочу выпустить предупреждение. Я хочу сделать это, найдя всю ссылку с 'bin\debug' в своем HintPath *. Я знаю, что ссылки - это Items в ItemGroup, с метаданными "HintPath".
Я ожидал чего-то подобного:
<Warning Text="Reference %(Reference.Identity) should be a project reference. HintPath: %(Reference.HintPath)"
Condition="%(Reference.HintPath).IndexOf('bin\debug') != -1"/>
Однако, похоже, я не могу использовать строковую функцию IndexOf. Я пробовал много перестановок выше, без успеха.
- Изменить: я знаю, что эта проверка не является полной, но я просто хочу уменьшить честные ошибки.
Ответы
Ответ 1
Используя MSBuild 4.0 Функции свойств, можно выполнить сравнение строк:
<Target Name="AfterBuild">
<Message Text="Checking reference... '%(Reference.HintPath)'" Importance="high" />
<Warning Text="Reference %(Reference.Identity) should be a project reference. HintPath: %(Reference.HintPath)"
Condition="$([System.String]::new('%(Reference.HintPath)').Contains('\bin\$(Configuration)'))" />
</Target>
Ответ 2
Сначала не то, что ваш синтаксис не подходит для вызова функций, это должно быть:
%(Reference.HintPath.IndexOf(...)) # Note: not supported by MSBuild
Однако функции свойств в MSBuild не разрешены в метаданных элементов, так что это тоже не поможет.
Что вы можете обойти это, вызвав отдельную цель, которая в основном предназначена для каждого элемента.
<Target Name="CheckProjectReferences">
<MSBuild
Projects="$(MSBuildProjectFullPath)"
Properties="Identity=%(Reference.Identity);HintPath=%(Reference.HintPath)"
Targets="_Warn"/>
</Target>
<Target Name="_Warn">
<Warning Text="Reference $(Identity) should be a project reference. HintPath: $(HintPath)"
Condition="$(HintPath.IndexOf('bin\debug')) != -1"/>
</Target>
Честно говоря, я не уверен, достаточно ли этого, чтобы поймать все "нарушения". Например, вышесказанное будет работать только для bin\debug
, но не для bin\debug
или других вариаций с смешанным корпусом, которые функционально эквивалентны. Чтобы искать их также, вам нужно вызвать перегрузку IndexOf(string, StringComparison)
, но просто выполните:
$(HintPath.IndexOf('bin\debug', System.StringComparison.OrdinalIgnoreCase))
Не будет работать, потому что разрешение перегрузки MSBuild выберет IndexOf(char, Int32)
и даст вам эту ошибку:
MSB4184: выражение "bin\debug".IndexOf(bin\debug, System.StringComparison.OrdinalIgnoreCase)" не может быть оценено. Строка должна быть ровно на один символ.
Итак, вам нужно убедить это, используя непосредственную перегрузку IndexOf(String, Int32, Int32, StringComparison)
:
$(HintPath.IndexOf('bin\debug', 0, 9, System.StringComparison.OrdinalIgnoreCase))
Вам может потребоваться также проверить bin\Release
или другие варианты. Я не уверен, что это лучший способ выяснить, ссылка должна быть ссылкой на проект, но если вы знаете (и для определенного контроля) свою среду, это может быть осуществимо.