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


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

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

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

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

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

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

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

Чтобы попробовать примеры в этом разделе, скопируйте их в файл шаблона, как описано в разделе "Создание кодаDesign-Time с помощью шаблонов текста 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 Directive.

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

Директива импорта совпадает с предложением 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. Это упрощает обсуждение модели с пользователями созданного приложения. Специфичные для домена языковые инструменты также создают набор строго типизированных классов, отражающих структуру модели. Дополнительные сведения см. в разделе "Создание кода на языке Domain-Specific".

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

В текстовом шаблоне времени разработки, если вы хотите ссылаться на файл в расположении относительно текстового шаблона, используйте 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.

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

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

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