Совершенно случайно обнаружил для себя замечательную вещь: оказывается можно настроить генерацию t4 не только в design time, но и в runtime! Это открывает широкие возможности генерации от всевозможных отчетов до C# кода, подгружаемого во время выполнения программы с помощью CSharpCodeProvider (если честно пока не могу придумать адекватного сценария, где такая runtime кодогенерация может понадобиться. Если есть идеи - прошу в комменты :) )
- Добавить референс на Microsoft.VisualStudio.TextTemplating.Interfaces.10.0.dll .
- Создать обычный t4 шаблон {TemplateName}.tt
- В качестве CustomTool указать TextTemplatingFilePreprocessor. Заодно можно указать CustomToolNamespace - неймспейс для генерируемых классов. После сохранения сгенерируется файл {TemplateName}.cs с двумя классами: partial {TemplateName} и {TemplateName}Base . Нас интересует класс {TemplateName} , а именно его главный метод TransformText(), который возвращает сгенерированный текст.
- Если для генерации нужны какие-то входные данные, то передать их не составляет проблем: надо создать файл со второй частью partial класса {TemplateName}, в которой прописать нужные свойства/поля и методы их заполнения.
Выглядеть вызов генерации будет примерно так:
string report = new SimpleReport( "qwe" ).TransformText();
Пример использования
Рассмотрим самый простой пример использования runtime t4 генерации: напишем простое консольное приложение, которое будет генерировать html-страницу с введенным пользователем текстом. Конечно такая программа сама по себе абсолютно бесполезна, но чтобы продемонстрировать возможности механизма - самое то ( cсылка на проект в github ).
public static class Program { public static void Main(params string[] args) { Console.WriteLine( "Enter any words end press enter to generate." ); var userText = Console.ReadLine(); var generatedHtml = new HtmlPageGenerator( userText ).TransformText(); var filePath = Path.Combine( Path.GetTempPath(), "htmlReport.html" ); File.WriteAllText( filePath, generatedHtml ); Process.Start( filePath ); } }
В Main() ничего особенного не происходит: получаем текст от пользователя, на основе него генерируем html страницу, сохраняем ее во временную папку и открываем в браузере.
В HtmlPageGenerator.tt надо прописать шаблон страницы:
<#@ template debug="false" hostSpecific="false" #> <html> <head></head> <body> <h1>Generated Page</h1> <b>Date:</b> <#= DateTime.Now #></br> <b>User:</b> <#= Environment.UserName #></br> <b>Text:</b> <#= this._customText #></br> </body> </html>
Чем хороша этот способ генерации страницы отчета - так это тем, что не нужно изобретать велосипед, не надо создавать свои классы-помощники для генерации страницы. Создавать и редактировать такой шаблон проще, так как вся разметка перед глазами.
Рядом с шаблоном создаем partial class HtmlPageGenerator:
public partial class HtmlPageGenerator { private string _customText; public HtmlPageGenerator(string customText) { _customText = customText; } }
Меняем CustomTool для HtmlPageGenerator.tt на TextTemplatingFilePreprocessor. После сохранения сгенерируется классы HtmlPageGenerator и HtmlPageGeneratorBase. Ниже приведен текст метода TransformText(), очищенный от лишних директив #line.
public virtual string TransformText() { this.Write("<html>\r\n<head></head>\r\n<body>\r\n<h1>Generated Page</h1>\r\n<b>Date:</b> "); this.Write(this.ToStringHelper.ToStringWithCulture(DateTime.Now)); this.Write("</br>\r\n<b>User:</b> "); this.Write(this.ToStringHelper.ToStringWithCulture(Environment.UserName)); this.Write("</br>\r\n<b>Text:</b> "); this.Write(this.ToStringHelper.ToStringWithCulture(this._customText)); this.Write("</br>\r\n</body>\r\n</html>\r\n"); return this.GenerationEnvironment.ToString(); }
Заключение
Runtime t4 генерация является простым, но мощным механизмом Visual Studio, который может здорово упростить жизнь в сценариях с генерацией всякой шаблонной всячины вроде отчетов или текстов писем.

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