- 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; } class Person { // Имя public String Name { get; set; } // Возраст public int Age { get; set; } // Пол public bool IsMale { get; set; } } <?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>
Где тип Person описывается следующим классом:
Для данной модели(коллекция, возвращаемая методом GetFriends()) необходимо создать представление в виде следующего XML файла:
Приступаем выполнению, и первое что делаем, это пишем шаблон(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> 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(); }
Самое главное мы реализовали, осталось лишь выполнить инициализацию нашего View Engine, указать ему шаблон, подсунуть модель и получить на выходе готовое представление:
Преимущества данного подхода заключается в том, что мы можем изменять шаблон (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