8 сентября 2012 г.

Шаблоны T4 в Visual Studio


Всем привет! Сегодня я хочу рассказать вам о замечательной технологии, которую предоставляет разработчикам Visual Studio – среда разработки шаблонов, известная под кодовым именем Т4.
Наверняка многие из вас сталкивались с такой очень распространенной задачей, как генерация писем. Одним из самых распространенных решений для таких задач являются XSLT трансформации. Вы определяете шаблон письма, включая различные операторы XSLT и затем вызываете специальный генератор, который осуществляет трансформацию, на основе переданных данных для письма. Данная технология отлично работала, и я сам ею пользовался, пока не столкнулся с механизмом Т4.

С помощью Т4 можно с легкостью сделать тоже самое, но при этом получить несколько преимуществ:
  1. В шаблонах Т4 вы можете с легкостью объявлять и использовать любые операции, доступные в языке C#;
  2. С легкостью привязывать статический текст шаблонов к ресурсным файлам вашего проекта;
  3. В процессе компиляции проекта шаблоны будут преобразованы в классы на языке C#, которые будут в свою очередь предварительно скомпилированы, а при выполнении – оптимизированы средой CLR.
Последнее преимущество будет весьма значимо, если для проекта крайне критично время построения шаблона. Скомпилированный класс с набором операций будет по умолчанию выполняться на порядок быстрее, чем любая XSLT трансформация.
Наверняка многие из вас сталкивались с шаблонами Т4, даже не подозревая об этом. Например отображения(View) в ASP.NET MVC работают при помощи шаблонов Т4. Entity Framework версии 4.0 использует этот механизм для автоматической генерации классов по схеме базы данных (правда в этом случае используется немного другой формат работы Т4, но об этом мы подробнее поговорим в другой статье).
Итак, хватит теории, давайте посмотрим как использовать Т4 на практике. Реализуем самый простой механизм генерации писем на основе шаблонов Т4.
Создадим новый проект и добавим туда новый элемент типа Preprocessed Text Template.
image
Visual Studio 2010 по умолчанию содержит все необходимые компоненты для Т4. Однако, есть один минус – в тексте шаблона отсутствует подсветка синтаксиса C#. Это довольно просто поправить – необходимо установить дополнение для Visual Studio, под названием “Visual T4”. Это очень крутая штука, которая обеспечит вам, не только подсветку синтаксиса, но и полный IntelliSense и валидацию кода.
После добавления элемента в проект, в Solution Explorer появится файл с расширением “.tt” и вложенный в него файл с расширением “.cs”.
image
Попробуйте открыть оба файла. Файл tt – это собственно наш шаблон, в котором вы можете определять нужную вам разметку письма. Файл cs – это класс-оболочка для шаблона, все команды и текст, который вы определите в шаблоне, будут автоматически преобразованы в последовательность команд на языке C# и записаны в метод TransformText этого файла.
Создадим шаблон, с письмо приветствия для нового пользователя:
   1:  <#@ template language="C#" #>
   2:  Welcome to our web-site!
   3:   
   4:  <#= DateTime.Now #>
Первая директива указывает на каком языке написан, встроенный в шаблон, код. Во второй строке мы выводим статический текст, а в третей строке выводится текущая дата и время, при помощи кода. Отлично, но неплохо было бы добавить сюда имя пользователя, то есть передать в наш шаблон какой-нибудь параметр.
Это можно сделать сделать двумя способами. Вы, возможно, обратили внимание, что класс-оболочка для шаблона объявлен с модификатором partial. Это значит, что он открыт для расширения и для этого можно не использовать наследование. Давайте расширим этот класс, добавив туда нужную нам переменную:
   1:      partial class MessageTemplate
   2:      {
   3:          public string UserName { get; set; }
   4:      }
Отлично, теперь мы сможем свободно использовать эту переменную в теле шаблона:
   1:  <#@ template language="C#" #>
   2:   
   3:  Hello, <#= this.UserName #>
   4:  Welcome to our web-site!
   5:  <#= DateTime.Now #>
Это – первый способ передачи параметров в шаблон. Чтобы узнать о втором способе, необходимо сначала научиться вызывать наши шаблоны. Для этого мы используем простое консольное приложение:
   1:      class Program
   2:      {
   3:          static void Main(string[] args)
   4:          {
   5:              var messageTmpl = new MessageTemplate();
   6:              messageTmpl.UserName = "Jack Daniels";
   7:              string message = messageTmpl.TransformText();
   8:   
   9:              Console.WriteLine(message);
  10:          }
  11:      }
Мы создали новый объект класса-оболочки шаблона и установили параметр, который мы ранее внедрили через partial класс. Далее, вызвав метод TransformText, мы получили готовое письмо с подставленными данными. Результат на окне консоли будет предсказуем:
image
Второй способ передачи параметров предполагает передачу параметров в формате ключ-значение. Изменим способ вызова шаблона, передав параметр через словарь (не забудьте удалить partial класс, в противном случае будет конфликт имен).
   1:      class Program
   2:      {
   3:          static void Main(string[] args)
   4:          {
   5:              var messageTmpl = new MessageTemplate();            
   6:   
   7:              messageTmpl.Session = new Dictionary<string, object>();
   8:              messageTmpl.Session.Add("UserName", "Jack Daniels");
   9:              messageTmpl.Initialize();
  10:   
  11:              string message = messageTmpl.TransformText();
  12:   
  13:              Console.WriteLine(message);            
  14:          }
  15:      }
Параметры записываются в словарь Session, который есть у каждого шаблона. Нужно отметить, что поле Session по умолчанию равно null и в случае передачи параметров таким способом, необходимо вызвать метод Initialize, иначе параметры переданы в шаблон не будут.
Сам шаблон также нужно модифицировать:
   1:  <#@ template language="C#" #>
   2:  <#@ Parameter Name="UserName" Type="System.String" #>
   3:   
   4:  Hello, <#= this.UserName #>
   5:   
   6:  Welcome to our web-site!
   7:   
   8:  <#= DateTime.Now #>

Каждый параметр, необходимо задекларировать, указав его имя и тип.
Как вы могли заметить первый способ, который предполагает создание partial класса, явно более удобен и легок в использовании, требует намного меньшего объема кода, а также является более красивым походом с точки зрения архитектуры приложения.
В этой статье был предоставлен краткий обзор шаблонов Т4 и был приведен пример реализации самой простой задачи при помощи этого механизма. Однако, возможности Т4 уходят далеко за рамки таких простых сценариев. Различные особенности и приемы, которые можно использовать в Т4 будут рассмотрены в следующей статье.

Комментариев нет:

Отправить комментарий