Создание кода во время разработки с помощью текстовых шаблонов T4

Текстовые шаблоны T4 во время разработки позволяют создавать код программы и другие файлы в проекте Visual Studio. Как правило, вы пишете шаблоны таким образом, чтобы они изменяли код, создаваемый в соответствии с данными из модели. Модель — это файл или база данных, содержащая ключевые сведения о требованиях приложения.

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

Примечание.

Модель — это источник данных, описывающий конкретный аспект приложения. Она может быть представлена в любой форме, в виде файла или базы данных. Он не должен находиться в какой-либо конкретной форме, например модели UML или языковой модели для конкретного домена. Типичные модели создаются в форме таблиц или XML-файлов.

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

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

Создание текстового шаблона T4 во время разработки

  1. Создайте проект Visual Studio или откройте существующий.

  2. Добавьте в проект текстовый файл шаблона и присвойте ему имя расширения .tt.

    Для этого в Обозреватель решений в контекстном меню проекта нажмите кнопку "Добавить>новый элемент". В диалоговом окне "Добавление нового элемента" выберите "Текстовый шаблон" в средней области.

    Обратите внимание, что свойство Custom Tool файла — TextTemplatingFileGenerator.

  3. Откройте файл . Он будет содержать следующие директивы:

    <#@ template hostspecific="false" language="C#" #>
    <#@ output extension=".txt" #>
    

    Если вы добавили шаблон в проект Visual Basic, атрибут языка будет "VB".

  4. Добавьте любой текст в конец файла. Например:

    Hello, world!
    
  5. Сохраните файл.

    Может появиться окно предупреждения системы безопасности, которое запрашивает подтверждение того, что вы хотите запустить шаблон. Щелкните OK.

  6. В Обозреватель решений разверните узел файла шаблона и найдите файл с расширением .txt. Файл содержит текст, созданный на основе шаблона.

    Примечание.

    Если проект является проектом Visual Basic, необходимо нажать кнопку "Показать все файлы ", чтобы просмотреть выходной файл.

Повторное создание кода

Шаблон выполняется, создавая дочерний файл, в следующих случаях:

  • Измените шаблон и измените фокус на другое окно Visual Studio.

  • Сохраните шаблон.

  • Щелкните "Преобразовать все шаблоны" в меню "Сборка". Это преобразует все шаблоны в решении Visual Studio.

  • В Обозреватель решений в контекстном меню любого файла выберите "Запустить настраиваемое средство". Используйте этот метод для преобразования выбранного набора шаблонов.

Вы также можете настроить проект Visual Studio, чтобы шаблоны выполнялись при изменении файлов данных, которые они читали. Дополнительные сведения см. в статье "Автоматическое создание кода".

Создание текста переменной

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

  1. Измените содержимое файла .tt:

    <#@ template hostspecific="false" language="C#" #>
    <#@ output extension=".txt" #>
    <#int top = 10;
    
    for (int i = 0; i<=top; i++)
    { #>
       The square of <#= i #> is <#= i*i #>
    <# } #>
    
  2. Сохраните .tt файл и проверьте созданный файл .txt еще раз. В нем перечисляются квадратные корни чисел от 0 до 10.

    Обратите внимание, что операторы заключены в символы <#...#>, а отдельные выражения — в символы <#=...#>. Дополнительные сведения см. в статье "Написание текстового шаблона T4".

    При написании создаваемого кода в Visual Basic template директива должна содержаться language="VB". Значение по умолчанию — "C#".

Отладка текстового шаблона времени разработки T4

Отладка текстового шаблона

  • Вставьте строку debug="true" в директиву template. Например:

    <#@ template debug="true" hostspecific="false" language="C#" #>

  • Задайте точки останова в шаблоне таким же образом, как для обычного кода.

  • Выберите шаблон Отладки T4 в контекстном меню файла текстового шаблона в Обозреватель решений.

    Шаблон запускается и останавливается в точках останова. Вы можете проверить переменные и выполнить код пошагово в обычном режиме.

Совет

debug="true" делает созданную схему кода более точной с текстовым шаблоном, вставляя дополнительные директивы нумерирования строк в созданный код. Если опустить эту строку, точки останова могут останавливать выполнение в неверном состоянии.

Но вы можете оставить предложение в директиве шаблона, даже если вы не отладите. Это приведет к незначительному снижению производительности.

Создание кода или ресурсов для решения

Можно создать различающиеся файлы программ в зависимости от модели. Модель представляет собой источник входных данных, такой как база данных, файл конфигурации, модель UML, модель DSL или другой источник. Обычно создается несколько файлов программы из одной модели. Для этого вы создаете файл шаблона для каждого создаваемого файла программы; для всех шаблонов задается чтение одной модели.

Создание программного кода или ресурсов

  1. Измените директиву output, чтобы создать файл нужного типа, например .CS, .VB, .RESX или .XML.

  2. Вставьте код, который создаст нужный вам код решения. Например, если требуется создать три объявления поля Integer в классе, используйте код:

    
    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ output extension=".cs" #>
    <# var properties = new string [] {"P1", "P2", "P3"}; #>
    // This is generated code:
    class MyGeneratedClass {
    <# // This code runs in the text template:
      foreach (string propertyName in properties)  { #>
      // Generated code:
      private int <#= propertyName #> = 0;
    <# } #>
    }
    
  3. Сохраните файл и проверьте созданный файл, который теперь содержит следующий код:

    class MyGeneratedClass {
      private int P1 = 0;
      private int P2 = 0;
      private int P3 = 0;
    }
    

Создающий код и созданный текст

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

Предыдущий пример имеет две версии. В одной версии создающий код написан на языке C#. В другой версии создающий код написан на языке Visual Basic. Но текст, созданный обоими из них, совпадает, и это класс C#.

Таким же образом можно использовать шаблон Visual C# для создания кода на любом языке. Созданный текст не должен находиться на определенном языке и не должен быть программным кодом.

Структура текстовых шаблонов

Как правило, рекомендуется разделять код шаблонов на две части.

  • Конфигурация или часть сбора данных, которая задает значения в переменных, но не содержит текстовые блоки. В предыдущем примере эта часть представлена кодом, инициализирующим properties.

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

  • Часть, создающая текст, (foreach(...){...} в примере), которая использует значения переменных.

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

Чтение файлов или других источников

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

<#@ assembly name="System.Xml.dll" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.IO" #>

Директива assembly делает указанную сборку доступной для кода шаблона таким же образом, как в разделе "Ссылки" проекта Visual Studio. Вам не нужно включать ссылку на System.dll, на которую ссылается автоматически. Директива import позволяет использовать типы, не используя полные имена, тем же способом, что и директива using в обычном файле программы.

Например, после импорта System.IO можно написать следующее:


<# var properties = File.ReadLines("C:\\propertyList.txt");#>
...
<# foreach (string propertyName in properties) { #>
...

Открытие файла с относительным путем

Чтобы загрузить файл из расположения, относительного для текстового шаблона, можно использовать this.Host.ResolvePath(). Чтобы использовать this.Host, необходимо задать hostspecific="true" в разделе template:

<#@ template debug="false" hostspecific="true" language="C#" #>

Затем можно написать код, например:

<# string filename = this.Host.ResolvePath("filename.txt");
  string [] properties = File.ReadLines(filename);
#>
...
<#  foreach (string propertyName in properties { #>
...

Кроме того, можно использовать this.Host.TemplateFile, определяющий имя текущего файла шаблона.

Тип this.Host (в VB, Me.Host) — Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost.

Получение данных из Visual Studio

Чтобы использовать службы, предоставляемые в Visual Studio, задайте hostspecific атрибут и загрузите сборку EnvDTE . Импорт Microsoft.VisualStudio.TextTemplating, содержащий GetCOMService() метод расширения. Затем можно использовать метод IServiceProvider.GetCOMService() для получения доступа к DTE и другим службам. Например:

<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#
  IServiceProvider serviceProvider = (IServiceProvider)this.Host;
  EnvDTE.DTE dte = (EnvDTE.DTE) serviceProvider.GetCOMService(typeof(EnvDTE.DTE));
#>

Number of projects in this VS solution:  <#= dte.Solution.Projects.Count #>

Совет

Текстовый шаблон выполняется в собственном домене приложений; доступ к службам предоставляется путем маршалинга. В этих обстоятельствах метод GetCOMService() надежнее, чем GetService().

Автоматическое создание кода

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

Если изменяется исходная модель, необходимо перезапустить все шаблоны в решении. Для этого вручную выберите "Преобразовать все шаблоны " в меню "Сборка ".

Если вы установили пакет SDK для моделирования Visual Studio, вы можете автоматически преобразовывать все шаблоны при выполнении сборки. Для этого измените файл проекта (CSPROJ или VBPROJ) в текстовом редакторе и добавьте следующие строки в конце файла после любых других <import> инструкций. В проекте в стиле ПАКЕТА SDK он может идти в любом месте файла проекта.

Примечание.

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

<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v17.0\TextTemplating\Microsoft.TextTemplating.targets" />
<PropertyGroup>
   <TransformOnBuild>true</TransformOnBuild>
   <!-- Other properties can be inserted here -->
</PropertyGroup>

Дополнительные сведения см. в разделе "Создание кода" в процессе сборки.

Отчеты об ошибках

Чтобы разместить сообщения об ошибках и предупреждениях в окне ошибок Visual Studio, можно использовать следующие методы:

Error("An error message");
Warning("A warning message");

Преобразование существующего файла в шаблон

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

Преобразование существующего файла в шаблон времени разработки

  1. В проект Visual Studio добавьте файл типа, который требуется создать, например .csфайл или .vb.resx файл.

  2. Проверьте созданный файл, чтобы убедиться, что он работает.

  3. В Обозреватель решений измените расширение имени файла на .tt.

  4. Проверьте следующие свойства TT-файла :

    Свойство Параметр
    Пользовательское средство = TextTemplatingFileGenerator
    Действие сборки = Не допускается
  5. Вставьте следующие строки в начало файла:

    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ output extension=".cs" #>
    

    Если вы хотите написать созданный код шаблона в Visual Basic, задайте language атрибут "VB" вместо "C#"него.

    Задайте для атрибута extension значение расширения файла того типа, который требуется создать, например .cs.resx или .xml.

  6. Сохраните файл.

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

    Убедитесь, что созданный файл содержит то же содержимое, что и исходный.

  7. Определите часть файла, которую требуется изменять. Например часть, которая отображается только при соблюдении определенных условий, или повторяемая часть, или часть, в которой варьируются определенные значения. Вставьте создающий код. Сохраните файл и убедитесь, что дочерний файл создается правильно. Повторите этот шаг.

Рекомендации по созданию кода

Ознакомьтесь с рекомендациями по написанию текстовых шаблонов T4.