Создание кода во время разработки с помощью текстовых шаблонов T4
Текстовые шаблоны времени разработки T4 позволяют создавать программный код и другие файлы в проекте Visual Studio. Как правило, шаблоны пишутся с той целью, чтобы использовать разный создаваемый ими код в соответствии с данными, полученными из модели. Модель — это файл или база данных, которая содержит основные сведения о требованиях приложения.
Например, можно создать модель, которая определяет рабочий процесс как таблицу или схему. На основе модели можно создать программу, выполняющую рабочий процесс. При изменении потребностей пользователей вы сможете обсудить с ними характеристики нового рабочего процесса. Повторное создание кода на основе рабочего процесса надежнее, чем обновление кода вручную.
Примечание
Модель — это источник данных, который описывает определенный аспект приложения.Она может быть представлена в любой форме, в виде файла или базы данных.Она не должна соответствовать определенной форме, например как модель UML или модель для доменного языка (DSL).Типичные модели создаются в форме таблиц или XML-файлов.
Вероятно, вы уже знакомы с созданием кода. При определении ресурсов в файле .resx в решении Visual Studio автоматически создается набор классов и методов. Файл ресурсов обеспечивает более простое и надежное редактирование ресурсов по сравнению с внесением изменений в классы и методы. Используя текстовые шаблоны, можно создавать код таким же образом на основе вашего собственного источника.
Текстовый шаблон содержит сочетание текста, который требуется создать, и программного кода, создающего переменные части текста. Программный код позволяет повторять или, при определенных условиях, пропускать части созданного текста. Созданный текст сам по себе может быть программным кодом, который формирует часть вашего приложения.
Создание текстового шаблона времени разработки T4
Создание шаблона времени разработки T4 в Visual Studio
Создайте проект Visual Studio или откройте уже имеющийся.
Например, в меню Файл выберите Создать, Проект.
Добавьте файл текстового шаблона в проект и присвойте ему имя с расширением .TT.
Для этого в Обозревателе решений в контекстном меню вашего проекта выберите Добавить, Новый элемент. В диалоговом окне Добавление нового элемента выберите в средней области элемент Текстовый шаблон.
Обратите внимание, что свойство Пользовательский инструмент файла имеет значение TextTemplatingFileGenerator.
Откройте файл. Он будет содержать следующие директивы:
<#@ template hostspecific="false" language="C#" #> <#@ output extension=".txt" #>
Если вы добавили шаблон в проект Visual Basic, для атрибута языка будет задано значение VB.
Добавьте любой текст в конец файла. Например:
Hello, world!
Сохраните файл.
На экран может быть выведено окно Предупреждение о безопасности с запросом подтверждения запуска шаблона. Нажмите кнопку ОК.
В Обозревателе решений разверните узел файла шаблона. В нем будет содержаться файл с расширением .TXT. Файл содержит текст, созданный на основе шаблона.
Примечание
Если вы работаете с проектом Visual Basic, чтобы увидеть выходной файл, нужно нажать кнопку Показать все файлы.
Повторное создание кода
Шаблон выполняется, создавая дочерний файл, в следующих случаях:
при редактировании шаблона и перемещении фокуса в другое окно Visual Studio;
при сохранении шаблона;
при выборе пункта Преобразовать все шаблоны в меню Сборка (это приведет к преобразованию всех шаблонов в решении Visual Studio);
при выборе в Обозревателе решений пункта Запустить пользовательский инструмент в контекстном меню любого файла. Используйте этот метод для преобразования выбранного набора шаблонов.
Вы также можете настроить проект Visual Studio так, чтобы шаблоны выполнялись при изменении считываемых ими файлов данных. Для получения дополнительной информации см. Regenerating the Code Automatically.
Создание переменного текста
Текстовые шаблоны позволяют программному коду изменять содержимое созданного файла.
Создание текста с помощью программного кода
Измените содержимое файла .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 #> <# } #>
<#@ template hostspecific="false" language="VB" #> <#@ output extension=".txt" #> <#Dim top As Integer = 10 For i As Integer = 0 To top #> The square of <#= i #> is <#= i*i #> <# Next #>
Сохраните 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 или другой источник. Как правило, на основе одной модели создается несколько файлов программ. Для этого вы создаете файл шаблона для каждого создаваемого файла программы; для всех шаблонов задается чтение одной модели.
Создание программного кода или ресурсов
Измените директиву output, чтобы создать файл нужного типа, например .CS, .VB, .RESX или .XML.
Вставьте код, который создаст нужный вам код решения. Например, если требуется создать три объявления поля 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; <# } #> }
<#@ template debug="false" hostspecific="false" language="VB" #> <#@ output extension=".cs" #> <# Dim properties = {"P1", "P2", "P3"} #> class MyGeneratedClass { <# For Each propertyName As String In properties #> private int <#= propertyName #> = 0; <# Next #> }
Сохраните файл и проверьте созданный файл, который теперь содержит следующий код:
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) { #>
...
<# For Each propertyName As String In
File.ReadLines("C:\\propertyList.txt")
#>
Открытие файла с относительным путем
Чтобы загрузить файл из расположения, относительного для текстового шаблона, можно использовать 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 { #>
...
<# Dim fileName = Me.Host.ResolvePath("propertyList.txt")
Dim properties = File.ReadLines(filename)
#>
...
<# For Each propertyName As String In properties
...
#>
Кроме того, можно использовать this.Host.TemplateFile, определяющий имя текущего файла шаблона.
Тип this.Host (в VB, Me.Host) — Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost.
Получение данных из Visual Studio
Для использования служб, предоставляемых в Visual Studio, задайте атрибут hostSpecific и загрузите сборку EnvDTE. Затем можно использовать метод IServiceProvider.GetCOMService() для получения доступа к DTE и другим службам. Например:
<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ assembly name="EnvDTE" #>
<#
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>:
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v11.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#, а затем постепенно вводите создающий код, изменяющий созданный файл.
Преобразование существующего файла в шаблон времени разработки
Добавьте в проект Visual Studio файл того типа, который требуется создать, например .cs .vb или .resx.
Проверьте созданный файл, чтобы убедиться, что он работает.
В Обозревателе решений измените расширение файла на .tt.
Проверьте следующие свойства файла .tt.
Пользовательский инструмент =
TextTemplatingFileGenerator
Действие построения =
Нет
Вставьте следующие строки в начало файла:
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ output extension=".cs" #>
Чтобы написать создающий код шаблона в Visual Basic, задайте для атрибута language значение "VB" вместо "C#".
Задайте для атрибута extension значение расширения файла того типа, который требуется создать, например .cs .resx или .xml.
Сохраните файл.
Создается дочерний файл с заданным расширением. Его свойства будут правильными для данного типа файла. Например, значением свойства Действие построения для CS-файла будет значение Компилировать.
Убедитесь, что созданный файл содержит то же содержимое, что и исходный.
Определите часть файла, которую требуется изменять. Например часть, которая отображается только при соблюдении определенных условий, или повторяемая часть, или часть, в которой варьируются определенные значения. Вставьте создающий код. Сохраните файл и убедитесь, что дочерний файл создается правильно. Повторите этот шаг.
Рекомендации по созданию кода
См. раздел Рекомендации по написанию текстовых шаблонов T4.
Следующие шаги
Следующий шаг |
Раздел |
---|---|
Написание и отладка расширенного текстового шаблона с помощью кода, который использует вспомогательные функции, включенные файлы и внешние данные. |
|
Создание документов на основе шаблонов во время выполнения. |
Создание текста во время выполнения с помощью текстовых шаблонов T4 |
Запуск создания текста за пределами Visual Studio. |
|
Преобразование данных в форме доменного языка. |
|
Написание процессоров директив для преобразования собственных источников данных. |