Расширение процесса компиляции BAML для регистрации дополнительных ошибок
Я столкнулся с такой же проблемой в прошлом году. Я писал свое собственное расширение, для которого я хотел ошибки во время компиляции в определенных сценариях, и обнаружил, что просто генерировать исключение из ProvideValue
не работает, потому что ProvideValue
не вызывается, пока XAML фактически не загружен и дерево объектов создан.
Я провел несколько экспериментов и обнаружил, что сообщение об ошибке компилятора для x:Static
является побочным продуктом оптимизации, выполняемой компилятором BAML. Формат BAML фактически имеет концепцию определенного члена определенного типа, поэтому, когда XAML содержит x:Static
, компилятор фактически заменяет его специальной записью, которая напрямую ссылается на член, а не содержит имя типа и метода. Это достигается путем явного распознавания класса StaticExtension. TypeExtension имеет аналогичную оптимизацию.
Я искал хуки, которые позволили бы мне вызывать собственный код во время компиляции BAML, но я не нашел ни одного. Компиляция BAML - это в основном прямая транслитерация в двоичный формат, соответствующий XAML, с несколькими конкретными оптимизациями, но в основном игнорирующим то, что он видит.
Я закончил тем, что добавил дополнительный шаг в процесс сборки, моделируя мой код из Microsoft.WinFX.targets
и других встроенных целевых файлов. Этот шаг сканирует XAML для моего расширения разметки, проверяет параметры и генерирует ошибку компиляции, если они не верны. Это делается полностью независимо от перевода на BAML. Когда все было сказано и сделано, потребовалась дополнительная работа в течение пары дней, но я многому научился.
Предостережение о создании собственного файла .targets
Если вы думаете о добавлении собственного файла .targets, вы должны знать, что, если вы не включите цель в раздел реестра SafeImports локального компьютера, Visual Studio и Expression Blend будут жаловаться на любой проект, в который входит ваш. файл целей. Этот ключ требует доступа администратора на компьютере для обновления. Это может или не может быть проблемой в зависимости от вашего сценария развертывания. (Например, установка MSI на компьютере могла бы исправить это, или вы могли бы вручную установить ключ, если у вас есть только несколько машин для разработки). В моем случае это не имело значения, так как мне уже был нужен специальный файл .targets для некоторых других вещей, которые я делал в этом проекте.
Ошибка регистрации из задачи сборки
Вам не нужен IVsErrorList для добавления ошибок в Visual Studio во время сборки (и если бы вы это сделали, вы бы не поддерживали сборки командной строки, Expression Blend и другие инструменты).
Все, что вам нужно сделать, это вызвать Log.LogErrror Log.LogWarning изнутри вашей задачи сборки, например:
public class CheckForErrorsInMyMarkupExtension : Task
{
... parameters here ...
public override Execute()
{
... code to load XAML and scan it for markup extension errors ...
... when you discover an error ...
Log.LogError("I saw an error");
}
}