В предыдущей заметке были показаны примеры делегатов шаблонов Razor. Давайте теперь посмотрим как они устроены.
Одной из возможностей движка представлений Razor, которая не так часто обсуждается, это возможность создания встроенных шаблонов. Их можно передавать в качестве аргумента в методы. Документации по данному вопросу не много, поэтому давайте взглянем на эту особенность подробнее.
Для начала посмотрим код, который создаётся при использовании встроенных шаблонов. Предположим есть метод Repeat(), который выводит заданный шаблон указанное число раз. Страница, использующая его, может выглядеть вот так:
<!DOCTYPE html>
<html>
<head>
<title>Repeat Helper Demo</title>
</head>
<body>
<p>Repeat Helper</p>
<ul>
@Repeat(10, @<li>List Item</li>);
</ul>
</body>
</html>
Результатом ее выполнения будет вывод списка из 10 пунктов с текстом "List Item".
Перейдем к коду метода Repeat(). Он может быть размещен как в статическом классе в папке App_Code, так и непосредственно внутри страницы. Воспользуемся последним вариантом и создадим блок @functions, который позволяет добавлять методы в генерируемый класс:
@using System.Text;
@functions {
public static IHtmlString Repeat(int times, Func<int, object> template)
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < times; i++) {
builder.Append(template(i));
}
return new HtmlString(builder.ToString());
}
}
Встроенный шаблон передается как делегат типа Func<int, object>. Результатом вызова является готовый HTML код. Обратите внимание на вызов делегата (строка 7). Ему передается параметр, о котором поговорим чуть позже.
А сейчас давайте посмотрим на генерируемый код, который соответствует вызову метода Repeat() в приведенном выше .cshtml файле:
this.Write(Repeat(10,item => new Microsoft.WebPages.Helpers.HelperResult(__writer => {
@__writer.Write(" ");
@__writer.Write("<li>List Item</li>");
})));
Как хорошо видно, в качестве делегата template передаётся лямбда-выражение, которое принимает единственный параметр item. При выполнении ее кода создается и возвращается объект типа HelperResult. Этот тип определен в каркасе ASP.Net Web Pages. В данном случае он является оберткой вокруг другого делегата, который и представляет исходный шаблон @<li>List Item</li>. Все завершается вызовами метода Write() (класс TextWriter) для вывода кода шаблона.
Таким образом, исходный встроенный шаблон превратился в метод, который при выполнении выводит сам шаблон. Использование HelperResult в качестве обертки, позволяется обращаться с ним как со строкой.
Вернемся к параметру item. Он позволяет предоставляет возможность передать в делегат данные для использования внутри шаблона. Для этого в шаблоне достаточно указать @item. В методе Repeat() в качестве параметра используется текущий номер сроки. Поэтому вот такой вариант вызова выведет список с элементами от "List Item 0" до "List Item 9":
@Repeat(10, @<li>List Item @item</li>);
В итоге, встроенные шаблоны можно использовать как параметры методов. Для этого необходимо задать параметр типа Func<T, object>, где T – любой необходимый по сценарию тип.
По материалам заметки "Inside Razor - Part 3 - Templates".