Создание T4 обрабатывает по шаблону во времени выполнения (время изготовления)?

Мы создаем внутреннее приложение, которое должно генерировать файлы HTML для загрузки в списки eBay. Мы надеемся использовать движок шаблонов для генерации файлов HTML на основе базы данных и статических полей, которые мы предопределили. Шаблон также должен иметь логические возможности (если тогда, foreach, и т.д.).

Мы посмотрели на T4, и это выглядит прекрасным, но мы ничего не видим о том, имеет ли это возможности, которые будут использоваться во времени выполнения, так, чтобы пользователь мог создать шаблон T4, и затем приложение может "скомпилировать" его и генерировать заключительный файл HTML. Действительно ли это возможно, и как?

В противном случае есть ли другие платформы, на которые мы должны смотреть, который имеет все эти возможности?

22
задан Amberite 21 February 2010 в 21:40
поделиться

5 ответов

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

В принципе, это работает как старый стиль ASP, вы окружаете код C# блоками <%...%>, и вы можете выдавать результаты, используя <%= выражение %>.

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

Вот как выглядит создание класса:

<%
var parameters = (string[])data;
var namespaceName = parameters[0];
var className = parameters[1];
%>
namespace <%= namespaceName %>
{
    public class <%= className %>
    {
    }
}

Конечно, вы можете перебирать объекты:

<% foreach (var parameter in parameters) { %>
<%= parameter %>
<% } %>

и помещать код в блоки if и т.д.

Библиотека классов выпущена на CodePlex здесь:

а также на NuGet.

Проект поставляется с примерами, скачайте исходники или просмотрите их онлайн.

Ответы на вопросы по электронной почте также здесь, чтобы другие видели:

  1. Все типы кода C# которые подходят под вызов метода могут быть скомпилированы в шаблоне. Он запускает обычный код C# 3.5, со всем, что это означает, нет никаких искусственных ограничений. Единственное, что нужно знать, это то, что любой код if, while, for, foreach и т.д., который содержит код шаблона для эмиссии, должен использовать скобки, вы не можете сделать однострочный блок типа if-then. Ограничение на вызов метода см. ниже.
  2. Параметр data соответствует тому, что было передано в качестве параметра методу .Generate(x) из вашего приложения, и имеет тот же тип. Если вы передаете объект, который вы определили в своих собственных библиотеках классов, вам необходимо добавить ссылку на него в код шаблона, чтобы правильно получить к нему доступ. (<%@ reference your.class.library.dll %>)
  3. Если вы повторно используете скомпилированный шаблон, то по сути это будет только вызов метода класса, никаких дополнительных накладных расходов на фактический вызов .Generate(). Если вы не вызовете .Compile() самостоятельно, то первый вызов .Generate() позаботится об этом. Также обратите внимание, что код выполняется в отдельном appdomain, поэтому есть небольшие накладные расходы на маршалинг, связанные с копированием параметра и результата туда и обратно. Код, однако, выполняется с обычной скоростью JITted .NET кода.

Пример if-блока:

<% if (a == b) { %>
This will only be output if a==b.
<% } %>

Искусственных ограничений на форматирование кода тоже нет, выбирайте тот стиль, который вам больше подходит:

<%
    if (a == b)
    {
%>
This will only be output if a==b.
<%
    }
%>

Только учтите, что все некодирующие части шаблона будут выводиться как есть, что означает, что табуляции и подобные им следующие %> блоки тоже будут выводиться.

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

Позвольте мне объяснить.

Шаблонный движок работает так: он создает файл .cs и передает его компилятору C#, этот файл .cs выглядит примерно так:

using directives

namespace SomeNamespace
{
    public class SomeClass
    {
        public string Render(object data)
        {
            ... all your code goes here
        }
    }
}

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

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

Func<DateTime, string> date2str = delegate(DateTime dt)
{
    return dt.ToString("G");
};

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

<%= date2str(DateTime.Now) %>

Единственное мое требование - не выкладывать файлы в сеть и не утверждать, что вы написали код, в остальном вы можете делать с ним все, что хотите.

Редактировать 23.04.2011: Исправлены ссылки на проект CodePlex.

16
ответ дан 29 November 2019 в 04:40
поделиться

Шаблоны T4 можно скомпилировать с помощью инструмента командной строки TextTransform.exe . Вы могли бы заставить ваше приложение создать файл .tt, а затем вызвать TextTransform.exe для генерации вывода.

3
ответ дан 29 November 2019 в 04:40
поделиться

Сборкой, реализующей преобразование текста T4, является Microsoft.VisualStudio.TextTemplating.dll, поставляемая вместе с Visual Studio.

Если вы хотите начать с первых принципов, вам нужно реализовать Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost, и передать свою реализацию в качестве аргумента Microsoft.VisualStudio.TextTemplating.Engine.ProcessTemplate(), который будет выполнять преобразование.

Это дает большую гибкость, чем обращение к TextTransform.exe.

Однако, если ваш код является поставляемым продуктом, неясно, каково лицензирование этой сборки, и есть ли у вас права на ее распространение вместе с вашим приложением.

Перераспространение этой сборки позволило бы избежать необходимости установки Visual Studio.

6
ответ дан 29 November 2019 в 04:40
поделиться

Т4 можно использовать во время выполнения.

Microsoft в действительности не поддерживает этот сценарий в .NET 3.5. Похоже, .NET 4.0 получит лучшую поддержку со стороны Microsoft.

Mono действительно обеспечивает некоторую поддержку этого сценария в .NET 3.5.

Я успешно доказал эту концепцию в .NET 3.5 с помощью реализации Mono T4, но готовое решение этой проблемы для .NET 3.5 потребует гораздо больше усилий, чем я вложил до сих пор.

Вы можете найти реализацию Mono T4 здесь:

https://github.com/mono/monodevelop/tree/master/main/src/addins/TextTemplating

Я задокументировал некоторые проблемы, с которыми я столкнулся пытается запустить шаблоны T4 из кода .NET здесь:

Варианты запуска шаблонов T4 из кода .NET

3
ответ дан 29 November 2019 в 04:40
поделиться

Если вы можете использовать Visual Studio 2010 для создания и редактирования шаблонов, то вы можете использовать предварительно скомпилированные шаблоны, которые были разработаны именно для этого сценария и являются поддерживаемым вариантом со стороны Microsoft.

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

http://www.olegsych.com/2009/09/t4-preprocessed-text-templates/

14
ответ дан 29 November 2019 в 04:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: