Написание текстового шаблона T4

Текстовый шаблон содержит текст, который будет создан на его основе. Например, шаблон, создающий веб-страницу, будет содержать html<>..." и все остальные стандартные части HTML-страницы. Вставленными в шаблон являются блоки управления, которые являются фрагментами кода программы. Блоки управления обеспечивают варьирующиеся значения и обеспечивают условность и повторяемость текста.

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

Текстовые шаблоны состоят из следующих частей.

  • Директивы — элементы, управляющие обработкой шаблона.

  • Текстовые блоки — содержимое, скопированное непосредственно в выходные данные.

  • Блоки управления — программный код, который вставляет значения переменных в текст и управляет условными или повторяющимися частями текста.

Чтобы попробовать примеры в этом разделе, скопируйте их в файл шаблона, как описано в разделе "Создание кода во время разработки" с помощью шаблонов текста T4. После редактирования файла шаблона сохраните его, а затем проверьте выходной TXT-файл .

Директивы

Директивы текстовых шаблонов предоставляют общие инструкции модулю текстовых шаблонов в отношении порядка создания кода преобразования и выходного файла.

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

<#@ output extension=".txt" #>

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

Текстовые блоки

Текстовый блок вставляет текст непосредственно в выходной файл. Для текстовых блоков нет особых правил форматирования. Например, следующий текстовый шаблон создаст текстовый файл со словом "Hello":

<#@ output extension=".txt" #>
Hello

Блоки управления

Блоки управления — это части программного кода, которые используются для преобразования шаблонов. Язык по умолчанию — C#, но для использования Visual Basic можно написать эту директиву в начале файла:

<#@ template language="VB" #>

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

Стандартные блоки управления

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

В файле шаблона можно смешивать любое число блоков текста и стандартных блоков управления. При этом нельзя помещать один блок управления в другой. Каждый стандартный блок управления отделяется символами <# ... #>.

Например, следующий блок управления и текстовый блок создают выходной файл, который содержит строку "0, 1, 2, 3, 4 Hello!":

<#
    for(int i = 0; i < 4; i++)
    {
        Write(i + ", ");
    }
    Write("4");
#> Hello!

Вместо использования явных операторов Write(), можно чередовать текст и код. В следующем примере печатается "Hello!" четыре раза:

<#
    for(int i = 0; i < 4; i++)
    {
#>
Hello!
<#
    }
#>

Можно вставить блок текста в любое место кода, где допускается вставка оператора Write();.

Примечание.

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

Блоки управления выражениями

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

Блоки управления выражениями разделяются символами <#= ... #>

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

<#= 2 + 3 #>

Обратите внимание, что открывающий символ имеет три символа "<#=".

Это выражение может включать любую переменную в области. Например, этот блок печатает строки цифр:

<#@ output extension=".txt" #>
<#
    for(int i = 0; i < 4; i++)
    {
#>
This is hello number <#= i+1 #>: Hello!
<#
    }
#>

Блоки управления возможностями класса

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

Блоки управления возможностями класса разделяются символами <#+ ... #>.

Например, следующий файл шаблона объявляет и использует метод:

<#@ output extension=".txt" #>
Squares:
<#
    for(int i = 0; i < 4; i++)
    {
#>
    The square of <#= i #> is <#= Square(i+1) #>.
<#
    }
#>
That is the end of the list.
<#+   // Start of class feature block
private int Square(int i)
{
    return i*i;
}
#>

Возможности класса необходимо помещать в конец файла, в котором они написаны. Однако можно включить файл (используя <#@include#>), содержащий возможность класса, даже если за директивой include следует текст и стандартные блоки.

Дополнительные сведения о блоках управления см. в разделе "Блоки элементов управления текстовым шаблоном".

Блоки возможностей класса могут содержать текстовые блоки

Вы можете написать метод, создающий текст. Например:

List of Squares:
<#
   for(int i = 0; i < 4; i++)
   {  WriteSquareLine(i); }
#>
End of list.
<#+   // Class feature block
private void WriteSquareLine(int i)
{
#>
   The square of <#= i #> is <#= i*i #>.
<#+
}
#>

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

Использование внешних определений

Сборки

Блоки кода шаблона могут использовать типы, определенные в наиболее часто используемых сборках .NET, таких как System.dll. Кроме того, можно добавить ссылку на другие сборки .NET или ваши собственные. Можно предоставить путь или строгое имя сборки:

<#@ assembly name="System.Xml" #>

Необходимо использовать абсолютные пути или стандартные имена макросов в пути. Например:

<#@ assembly name="$(SolutionDir)library\MyAssembly.dll" #>

Директива сборки не действует в предварительно обработанном текстовом шаблоне.

Дополнительные сведения см. в директиве T4 Assembly.

Пространства имен

Директива import соответствует выражению using в C# или выражению imports в Visual Basic. Она позволяет ссылаться на типы в коде, не используя полное имя:

<#@ import namespace="System.Xml" #>

Число используемых директив assembly и import не ограничено. Их нужно размещать до блоков управления и текста.

Дополнительные сведения см. в директиве импорта T4.

Включение кода и текста

Директива include вставляет текст из другого файла шаблона. Например, эта директива вставляет содержимое файла test.txt:

<#@ include file="c:\test.txt" #>

Включенное содержимое обрабатывается почти так же, как если бы оно было частью включающего текстового шаблона. При этом можно включить файл, содержащий блок возможностей класса <#+...#>, даже если за директивой include следуют обычный текст и стандартные блоки управления.

Дополнительные сведения см. в директиве T4 Include.

Служебные методы

Существует несколько методов, таких как Write(), которые всегда можно использовать в блоке управления. Они включают методы, помогающие создать отступы для вывода или отчеты об ошибках.

Кроме того, вы можете создать собственный набор служебных методов.

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

Преобразование данных и моделей

Наиболее полезная сфера применения текстовых шаблонов — создание материалов на основе содержимого источника, такого как модель, база данных или файл данных. Шаблон извлекает данные и изменяет их формат. Коллекция шаблонов может преобразовать подобный источник в несколько файлов.

Существует несколько способов считывания исходного файла.

Чтение файла в текстовом шаблоне. Это самый простой способ получения данных в шаблоне:

<#@ import namespace="System.IO" #>
<# string fileContent = File.ReadAllText(@"C:\myData.txt"); ...

Загрузите файл в виде навигации модели. Более эффективный способ — это чтение данных как модели, по которой может перемещаться код текстового шаблона. Например, можно загрузить XML-файл и выполнять навигацию по этому файлу с помощью выражений XPath. Можно также использовать xsd.exe для создания набора классов, с помощью которых можно считывать XML-данные.

Измените файл модели в схеме или форме. Инструменты языка для конкретного домена предоставляют средства, позволяющие изменять модель в виде схемы или формы Windows. Это упрощает обсуждение модели с пользователями созданного приложения. Инструменты языка для конкретного домена также создают набор строго типизированных классов, которые отражают структуру модели. Дополнительные сведения см. в разделе "Создание кода на языке для конкретного домена".

Относительные пути файлов в шаблонах времени разработки

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

<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ import namespace="System.IO" #>
<#
 // Find a path within the same project as the text template:
 string myFile = File.ReadAllText(this.Host.ResolvePath("MyFile.txt"));
#>
Content of MyFile.txt is:
<#= myFile #>

Можно также получить другие службы, предоставляемые узлом. Дополнительные сведения см. в разделе "Доступ к Visual Studio" или другим узлам из шаблона.

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

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

(Это не верно в текстовом шаблоне времени выполнения, который предоставляет код, скомпилированный вместе с остальным кодом.)

Редактирование шаблонов

Специализированные редакторы текстовых шаблонов можно загрузить из каталога диспетчера расширений в Интернете. В меню "Сервис" щелкните "Диспетчер расширений". Щелкните онлайн-коллекцию и используйте средство поиска.