Поделиться через


Вызов преобразования текста в процессе сборки

Преобразование текста можно вызвать как часть процесса сборки решения Visual Studio. Существуют задачи сборки, специализированные для преобразования текста. Задачи сборки T4 выполняют текстовые шаблоны в режиме проектирования, а также компилируют текстовые шаблоны во время выполнения (предварительно обработанные).

Есть некоторые различия в том, что могут делать задачи сборки, в зависимости от используемой системы сборки. При создании решения в Visual Studio текстовый шаблон может получить доступ к API Visual Studio (EnvDTE), если задан атрибут hostspecific="true". Но это не так, если вы создаете решение из командной строки или инициируете сборку сервера с помощью Visual Studio. В этих случаях сборка выполняется MSBuild, и используется другой хост T4. Это означает, что при создании текстового шаблона с помощью MSBuild невозможно получить доступ к таким же именам файлов проекта. Однако вы можете передать сведения о среде в текстовые шаблоны и обработчики директив с помощью параметров сборки.

Настройка компьютеров

Чтобы включить задачи сборки на компьютере разработки, установите пакет SDK моделирования для Visual Studio.

Замечание

Компонент преобразования текстовых шаблонов автоматически устанавливается в рамках рабочей нагрузки разработки расширений Visual Studio . Вы также можете установить его на вкладке "Отдельные компоненты " Установщика Visual Studio в категориях SDK, библиотек и платформ . Установите компонент sdk для моделирования на вкладке "Отдельные компоненты ".

Если сервер сборки работает на компьютере, на котором не установлен Visual Studio, скопируйте следующие файлы на компьютер сборки с компьютера разработки:

  • %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VisualStudio\v16.0\TextTemplating

    • Microsoft.VisualStudio.TextTemplating.Sdk.Host.15.0.dll
    • Microsoft.TextTemplating.Build.Tasks.dll
    • Microsoft.TextTemplating.targets
  • %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\VSSDK\VisualStudioIntegration\Common\Assemblies\v4.0

    • Microsoft.VisualStudio.TextTemplating.15.0.dll
    • Microsoft.VisualStudio.TextTemplating.Interfaces.15.0.dll
    • Microsoft.VisualStudio.TextTemplating.VSHost.15.0.dll
  • %ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\Common7\IDE\PublicAssemblies

    • Microsoft.VisualStudio.TextTemplating.Modeling.15.0.dll

Подсказка

Если при выполнении целевых объектов сборки TextTemplating на сервере сборки у вас возникает MissingMethodException для метода Microsoft.CodeAnalysis, убедитесь, что сборки Roslyn находятся в каталоге Roslyn, который расположен в том же каталоге, что и исполняемый файл сборки (например, msbuild.exe).

Изменение файла проекта

Измените файл проекта, чтобы настроить некоторые функции в MSBuild, например импорт целевых объектов преобразования текста.

В обозревателе решений выберите " Выгрузить " в меню правой кнопкой мыши проекта. Это позволяет изменять CSPROJ-файл или VBPROJ-файл в редакторе XML. После завершения редактирования нажмите кнопку "Перезагрузить".

Импорт целевых объектов преобразования текста

В Vbproj или CSPROJ-файле найдите последнюю Import Project строку.

После этой строки, если она существует, вставьте импорт Text Templating:

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v17.0\TextTemplating\Microsoft.TextTemplating.targets" />

Преобразование шаблонов в сборке

Существуют некоторые свойства, которые можно вставить в файл проекта для управления задачей преобразования:

  • Выполните задачу преобразования в начале каждой сборки:

    <PropertyGroup>
        <TransformOnBuild>true</TransformOnBuild>
    </PropertyGroup>
    
  • Например, перезаписывать файлы, доступные только для чтения, так как они не извлекаются:

    <PropertyGroup>
        <OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>
    </PropertyGroup>
    
  • Преобразуйте каждый шаблон каждый раз:

    <PropertyGroup>
        <TransformOutOfDateOnly>false</TransformOutOfDateOnly>
    </PropertyGroup>
    

    По умолчанию задача T4 MSBuild повторно создает выходной файл, если он старше:

    • его файл шаблона
    • все файлы, включенные
    • все файлы, которые ранее были прочитаны шаблоном или обработчиком директив, который он использует

    Это более мощный тест зависимостей, чем используется командой Преобразования всех шаблонов в Visual Studio, которая сравнивает только даты шаблона и выходной файл.

Чтобы выполнить только преобразования текста в проекте, вызовите задачу TransformAll:

msbuild myProject.csproj /t:TransformAll

Чтобы преобразовать определенный текстовый шаблон, выполните указанные действия.

msbuild myProject.csproj /t:Transform /p:TransformFile="Template1.tt"

В TransformFile можно использовать подстановочные знаки:

msbuild dsl.csproj /t:Transform /p:TransformFile="GeneratedCode\**\*.tt"

Управление исходным кодом

Встроенная интеграция с системой управления версиями отсутствует. Однако можно добавить собственные расширения, например, чтобы извлечь и проверить созданный файл. По умолчанию задача преобразования текста избегает перезаписи файла, помеченного как доступный только для чтения. При обнаружении такого файла ошибка регистрируется в списке ошибок Visual Studio, и задача завершается ошибкой.

Чтобы указать, что файлы только для чтения должны быть перезаписаны, вставьте это свойство:

<OverwriteReadOnlyOutputFiles>true</OverwriteReadOnlyOutputFiles>

Если вы не настроите шаг после обработки, предупреждение будет включено в список ошибок при перезаписи файла.

Настройка процесса сборки

Преобразование текста происходит перед другими задачами в процессе сборки. Вы можете определить задачи, которые вызываются до и после преобразования, задав свойства $(BeforeTransform) и $(AfterTransform):

<PropertyGroup>
    <BeforeTransform>CustomPreTransform</BeforeTransform>
    <AfterTransform>CustomPostTransform</AfterTransform>
</PropertyGroup>
<Target Name="CustomPreTransform">
    <Message Text="In CustomPreTransform..." Importance="High" />
</Target>
<Target Name="CustomPostTransform">
    <Message Text="In CustomPostTransform..." Importance="High" />
</Target>

В AfterTransform вы можете ссылаться на списки файлов:

  • GeneratedFiles — список файлов, написанных процессом. Для тех файлов, которые перекроют существующие файлы, доступные только для чтения, %(GeneratedFiles.ReadOnlyFileOverwritten) будут иметь значение true. Эти файлы можно извлечь из системы управления версиями.

  • NonGeneratedFiles — список файлов, доступных только для чтения, которые не были перезаписаны.

Например, вы определяете задачу для проверки сгенерированных файлов.

OutputFilePath и OutputFileName

Эти свойства используются только MSBuild. Они не влияют на создание кода в Visual Studio. Они перенаправляют созданный выходной файл в другую папку или файл. Целевая папка уже должна существовать.

<ItemGroup>
  <None Include="MyTemplate.tt">
    <Generator>TextTemplatingFileGenerator</Generator>
    <OutputFilePath>MyFolder</OutputFilePath>
    <LastGenOutput>MyTemplate.cs</LastGenOutput>
  </None>
</ItemGroup>

Полезная папка для перенаправления $(IntermediateOutputPath).

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

<ItemGroup>
  <None Include="MyTemplate.tt">
    <Generator>TextTemplatingFileGenerator</Generator>
    <OutputFileName>MyOutputFileName.cs</OutputFileName>
    <LastGenOutput>MyTemplate.cs</LastGenOutput>
  </None>
</ItemGroup>

Задание имени выходного файла (OutputFileName) или пути выходного файла (OutputFilePath) не рекомендуется, если вы также трансформируете шаблоны внутри Visual Studio с помощью функции Transform All или запускаете однофайловый генератор. В конечном итоге вы будете использовать различные пути к файлам в зависимости от того, как вы активировали преобразование. Это может быть запутано.

Добавьте ссылки и пути включения

Хост имеет набор путей по умолчанию, в которых выполняется поиск сборок, на которые ссылаются шаблоны. Чтобы добавить этот набор, выполните указанные ниже действия.

<ItemGroup>
    <T4ReferencePath Include="$(VsIdePath)PublicAssemblies\" />
    <!-- Add more T4ReferencePath items here -->
</ItemGroup>

Чтобы задать папки, в которых будут искаться файлы include, укажите список, разделенный точкой с запятой. Обычно добавляется в существующий список папок.

<PropertyGroup>
    <IncludeFolders>
$(IncludeFolders);$(MSBuildProjectDirectory)\Include;AnotherFolder;And\Another</IncludeFolders>
</PropertyGroup>

Передача данных контекста сборки в шаблоны

Значения параметров можно задать в файле проекта. Например, можно передать свойства сборки и переменные среды:

<ItemGroup>
  <T4ParameterValues Include="ProjectFolder">
    <Value>$(ProjectDir)</Value>
    <Visible>false</Visible>
  </T4ParameterValues>
</ItemGroup>

В текстовом шаблоне задайте hostspecific в директиве шаблона. Используйте директиву параметра для получения значений:

<#@template language="c#" hostspecific="true"#>
<#@ parameter type="System.String" name="ProjectFolder" #>
The project folder is: <#= ProjectFolder #>

В обработчике директив можно вызвать ITextTemplatingEngineHost.ResolveParameterValue:

string value = Host.ResolveParameterValue("-", "-", "parameterName");

Замечание

ResolveParameterValue получает данные из T4ParameterValues только при использовании MSBuild. При преобразовании шаблона с помощью Visual Studio параметры имеют значения по умолчанию.

Используйте свойства проекта в сборке и директивах включения

Макросы Visual Studio, такие как $(SolutionDir), не работают в MSBuild. Вместо этого можно использовать свойства проекта.

Измените файл .csproj или .vbproj, чтобы определить свойство проекта. В этом примере определяется свойство myLibFolder:

<!-- Define a project property, myLibFolder: -->
<PropertyGroup>
    <myLibFolder>$(MSBuildProjectDirectory)\..\libs</myLibFolder>
</PropertyGroup>

<!-- Tell the MSBuild T4 task to make the property available: -->
<ItemGroup>
    <T4ParameterValues Include="myLibFolder">
      <Value>$(myLibFolder)</Value>
    </T4ParameterValues>
  </ItemGroup>

Теперь вы можете использовать свойство проекта в сборке кода и применять директивы.

<#@ assembly name="$(myLibFolder)\MyLib.dll" #>
<#@ include file="$(myLibFolder)\MyIncludeFile.t4" #>

Эти директивы получают значения из T4parameterValues как в MSBuild, так и в хостах Visual Studio.

Вопросы и ответы

Почему нужно преобразовать шаблоны на сервере сборки? Я уже преобразовал шаблоны в Visual Studio, прежде чем я проверил свой код.

При обновлении включенного файла или другого файла, считываемого шаблоном, Visual Studio не преобразует файл автоматически. Преобразование шаблонов в рамках сборки гарантирует, что все актуально.

Какие другие параметры существуют для преобразования текстовых шаблонов?

  • В шаблоне T4 MSBuild есть хорошее руководство. %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VisualStudio\v17.0\TextTemplating\Microsoft.TextTemplating.targets