Мы создаем внутреннее приложение, которое должно генерировать файлы HTML для загрузки в списки eBay. Мы надеемся использовать движок шаблонов для генерации файлов HTML на основе базы данных и статических полей, которые мы предопределили. Шаблон также должен иметь логические возможности (если тогда, foreach, и т.д.).
Мы посмотрели на T4, и это выглядит прекрасным, но мы ничего не видим о том, имеет ли это возможности, которые будут использоваться во времени выполнения, так, чтобы пользователь мог создать шаблон T4, и затем приложение может "скомпилировать" его и генерировать заключительный файл HTML. Действительно ли это возможно, и как?
В противном случае есть ли другие платформы, на которые мы должны смотреть, который имеет все эти возможности?
У меня есть похожий набор классов, который я использую для этого, встраивая генерацию шаблонизированного текста в программное обеспечение.
В принципе, это работает как старый стиль 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.
Проект поставляется с примерами, скачайте исходники или просмотрите их онлайн.
Ответы на вопросы по электронной почте также здесь, чтобы другие видели:
data
соответствует тому, что было передано в качестве параметра методу .Generate(x)
из вашего приложения, и имеет тот же тип. Если вы передаете объект, который вы определили в своих собственных библиотеках классов, вам необходимо добавить ссылку на него в код шаблона, чтобы правильно получить к нему доступ. (<%@ reference your.class.library.dll %>
).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.
Шаблоны T4 можно скомпилировать с помощью инструмента командной строки TextTransform.exe . Вы могли бы заставить ваше приложение создать файл .tt, а затем вызвать TextTransform.exe для генерации вывода.
Сборкой, реализующей преобразование текста T4, является Microsoft.VisualStudio.TextTemplating.dll, поставляемая вместе с Visual Studio.
Если вы хотите начать с первых принципов, вам нужно реализовать Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost, и передать свою реализацию в качестве аргумента Microsoft.VisualStudio.TextTemplating.Engine.ProcessTemplate(), который будет выполнять преобразование.
Это дает большую гибкость, чем обращение к TextTransform.exe.
Однако, если ваш код является поставляемым продуктом, неясно, каково лицензирование этой сборки, и есть ли у вас права на ее распространение вместе с вашим приложением.
Перераспространение этой сборки позволило бы избежать необходимости установки Visual Studio.
Т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 здесь:
Если вы можете использовать Visual Studio 2010 для создания и редактирования шаблонов, то вы можете использовать предварительно скомпилированные шаблоны, которые были разработаны именно для этого сценария и являются поддерживаемым вариантом со стороны Microsoft.
Вы разрабатываете шаблон в Visual Studio, предварительно компилируете его и развертываете сборку, которая не зависит от Visual Studio вместе с вашим приложением.
http://www.olegsych.com/2009/09/t4-preprocessed-text-templates/