Недавно в блоге Фила Хаака (Phil Haack) была опубликована интересная заметка. В ней шла речь о достаточно необычной возможности движка представлений Razor.
Эту идею подсказал Дэвид Фаулер (David Fowler). Как же что же такое делегаты шаблонов Razor (Templated Razor Delegates)? Давайте начнем с примера кода:
@{
Func<dynamic, object> b = @<strong>@item</strong>;
}
<span>This sentence is @b("In Bold").</span>
Как можно догадаться, текст "In Bold" будет выведен жирным шрифтом. Обратите внимание, что создаваемый делегат будет иметь тип Func<dynamic, HelperResult>. Кроме того, в коде присутствует магическое значение @item. Это, по сути, единственный параметр делегата, но шаблон может обращаться к нему столько раз, сколько необходимо.
Пример выше достаточно простой. Почему бы не попробовать его использовать при создании помощника (helper). Давайте перейдем к примеру, который действительно может быть полезен в работе. Это будет метод, который выводит список, используя предоставленный шаблон:
public static class RazorExtensions
{
public static HelperResult List<T>(this IEnumerable<T> items,
Func<T, HelperResult> template)
{
return new HelperResult(writer => {
foreach (var item in items) {
template(item).WriteTo(writer);
}
});
}
}
Метод List() принимает в качестве параметра шаблон Razor. Использовать его можно так:
@{
var items = new[] { "one", "two", "three" };
}
<ul>
@items.List(@<li>@item</li>)
</ul>
Как уже было отмечено выше, аргумент метода (@<li>@item</li>) будет представлен как делегат типа Func<dynamic, HelperResult>.
Самое интересное заключается в том, что созданный метод хорошо подходит для повторного использования в разных сценариях. Давайте вместо списка выведем таблицу:
@{
var comics = new[] {
new ComicBook {Title = "Groo", Publisher = "Dark Horse Comics"},
new ComicBook {Title = "Spiderman", Publisher = "Marvel"}
};
}
<table>
@comics.List(
@<tr>
<td>@item.Title</td>
<td>@item.Publisher</td>
</tr>)
</table>
По материалам заметки "Templated Razor Delegates".