Ответ 1
У меня есть аналогичный набор классов, который я использую для этого, встраивание шаблонного текста в программное обеспечение.
В основном, он работает как старый ASP, вы окружаете код С# в блоках <%...%>
, и вы можете генерировать результаты с помощью <%= expression %>
.
Вы можете передать один объект в код шаблона, который, конечно, может быть любым типом объекта, который вам нравится, или просто массив параметров. Вы также можете ссылаться на свои собственные сборки, если вы хотите выполнить собственный код.
Вот как выглядел бы излучение класса:
<%
var parameters = (string[])data;
var namespaceName = parameters[0];
var className = parameters[1];
%>
namespace <%= namespaceName %>
{
public class <%= className %>
{
}
}
Вы можете, конечно, перебирать вещи:
<% foreach (var parameter in parameters) { %>
<%= parameter %>
<% } %>
и введите код в if-blocks и т.д.
Библиотека классов выпущена на CodePlex здесь:
а также NuGet.
Проект поставляется с примерами, загружает источник или просматривает его в Интернете.
Чтобы ответить на вопросы по электронной почте, также здесь, чтобы другие могли видеть:
- Все типы кода С#, которые вписываются в вызов метода, могут быть скомпилированы в шаблоне. Он работает с обычным кодом С# 3.5, со всем, что означает, нет никаких искусственных ограничений. Единственное, что нужно знать, это то, что любой код if, while, foreach и т.д., Содержащий код шаблона для emit, должен использовать фигурные скобки, вы не можете сделать однострочный блок if-then type. См. Ниже ограничение метода.
- Параметр
data
соответствует тому, что было передано в качестве параметра метода.Generate(x)
из вашего приложения, и имеет тот же тип. Если вы передадите объект, определенный в ваших собственных библиотеках классов, вам нужно добавить ссылку на код шаблона, чтобы правильно его получить. (<%@ reference your.class.library.dll %>
) - Если вы повторно используете скомпилированный шаблон, он по сути будет только вызовом метода для класса, при фактическом вызове
.Generate()
никаких дополнительных накладных расходов не будет. Если вы не вызываете.Compile()
самостоятельно, первый вызов.Generate()
позаботится об этом. Также обратите внимание, что код запускается в отдельном домене приложения, поэтому есть небольшая служебная информация, связанная с копированием параметра и результатом взад и вперед. Код, однако, работает с нормальной скоростью кода 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 и передает его компилятору С#, этот файл .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.