- System.Web.Mvc.WebFormViewEngine
- Brail
- NDjango
- NHaml
- NVelocity
- Spark View Engine
Использование каждого, это дело вкуса (сравнение), но в этой статье я хотел бы поделиться опытом использования мною NVelocity в своем проекте. Скачать NVelocity можно как отдельно в виде библиотеки, так и в составе СastleProject. Последнее идет полной сборкой и добавляет в Visual Studio поддержку intellisense. После того как вы установили NVelocity, необходимо добавить в проекте reference, это сделает доступным следующие пространства имен:
using NVelocity;
using NVelocity.App;
using NVelocity.Context;
Подготовительная часть пройдена. Вернемся к нашему проекту и озвучим постановку задачи: дан источник данных, возвращающий коллекцию элементов типа Person, оформленный в виде статического метода:
static Person[] GetFriends()
{
Person[] group =
{
new Person { Name = "Илья", Age = 24, IsMale = true },
new Person { Name = "Алексей", Age = 22, IsMale = true },
new Person { Name = "Наталья", Age = 25, IsMale = false },
new Person { Name = "Борис", Age = 23, IsMale = true }
};
return group;
}
Где тип Person описывается следующим классом:
class Person
{
// Имя
public String Name { get; set; }
// Возраст
public int Age { get; set; }
// Пол
public bool IsMale { get; set; }
}
Для данной модели(коллекция, возвращаемая методом GetFriends()) необходимо создать представление в виде следующего XML файла:
<?xml version="1.0" encoding="utf-8"?>
<group name="Друзья">
<person
name="ИЛЬЯ"
age="24"
gender="м" />
<person
name="АЛЕКСЕЙ"
age="22"
gender="м" />
<person
name="НАТАЛЬЯ"
age="25"
gender="ж" />
<person
name="БОРИС"
age="23"
gender="м" />
</group>
Приступаем выполнению, и первое что делаем, это пишем шаблон(Template). Шаблон реализуется на интуитивно понятном языке Velocity Template Language (VTL). Для этого добавим в проект файл xmlTemplate.vm со следующим содержимым:
## Инициализация локальных переменных
#set($male = "м")
#set($female = "ж")
## Шаблон
<?xml version="1.0" encoding="utf-8"?>
<group name="$groupName">
#foreach( $person in $group)
<person
name="$person.Name.ToUpper()"
age="$person.Age"
gender="#if($person.IsMale)$male#else$female#end" />
#end
</group>
Самое главное мы реализовали, осталось лишь выполнить инициализацию нашего View Engine, указать ему шаблон, подсунуть модель и получить на выходе готовое представление:
static void Main(string[] args)
{
// Получим модель
Person[] group = GetFriends();
// Инициализируем ViewEngine.
Velocity.Init();
// Инициализируем контекст моделью.
VelocityContext context = new VelocityContext();
context.Put("groupName", "Друзья");
context.Put("group", group);
using (StringWriter writer = new StringWriter())
{
// Используя шаблон, построим отображение модели.
Velocity.MergeTemplate
(
@"xmlTemplate.vm",
Encoding.UTF8.WebName,
context,
writer
);
Console.WriteLine(writer.GetStringBuilder().ToString());
}
Console.ReadKey();
}
Преимущества данного подхода заключается в том, что мы можем изменять шаблон (xmlTemplate.vm) и при этом не трогая(!) исходный код. Во-вторых, исходный код программы при таком подходе лишен громоздких, формирующих представление модели, конструкций. В-третьих, получившийся шаблон не зависит ни от платформы, ни от языка на котором реализован сам движок.
Не вижу никакого смысла использовать в данном случае "View Engine"-движков, имхо. Можно обойтись простой xml-сериализацией. Пример не демонстрирует выигрыша от использования View Engine, но все равно спс за статью
ОтветитьУдалить@Wanderer
ОтветитьУдалитьСпасибо за комментарий.
На данном примере да. Но все же, если мы захотим получить не xml, а например представление в json (задача на будущее), то здесь нам не обойтись без View Engine.
Да и поправить шаблон гораздо удобнее и нагляднее, нежели перестраивать сериализацию.
ну почему же, можно воспользоваться стандартными средствами для сериализвации в json (класс System.Runtime.Serialization.Json.DataContractJsonSerializer). Хотя это все тот же частный случай, как и с xml.. Я думаю не стоит говорить о том, что лучше использовать в данном случае или сериализацию (xml или json) или View Engine - дело вкуса, как и в том так и в другом случае будут накладные расходы: в первом случае, если понадобиться изменить сериализуемое представление, во-втором - изучение определенного View Engine движка.
ОтветитьУдалитьХотелось именно посмотреть на случаи, где View Engine действительно был бы необходим.
@Wanderer
ОтветитьУдалитьДля более сложных шаблонов, например получить HTML, RTF или CSV, YAML или XSL-FO.
Здесь главное использование подхода Model-View (шаблон).
IsMale = true
ОтветитьУдалитьпопахивает дискриминацией
@hazzik
ОтветитьУдалитьДа не, Вам показалось :).
А если серьезно, то конечно нужно было бы завести enum.
Мне тоже нравится NVelocity. Если говорить о реальных примерах применения, то часто template engines используются для генерации электронных писем. Особенно когда нужно генерировать сложное письмо с циклами и условиями. Но, к сожалению, реализация Velocity под .NET не лишена недостатков. Сами castle признаются, что, например, макросы работают не всегда корректно.
ОтветитьУдалить@admax
ОтветитьУдалитьСогласен, не все у них гладко. Просто сам язык Velocity меня привлекает. Да и много других шаблонизаторов основаны на Velocity.
Я так понимаю, NVelocity можно использовать для кодогенерации. Или я ошибаюсь?
ОтветитьУдалить@Barsym
ОтветитьУдалитьДа, можно.
Но лучше код генерировать этим: T4 Templates in Visual Studio for Code Generation