Оценка оператора If с помощью динамического LINQ

В моем предыдущем посте я описал основы нового ASP.NET MVC View Engine, над которым я начал работать на основе популярного Smarty PHP View Engine.

Вот мои текущие цели для этого проекта:

  1. Реализовать все встроенные функции от Smarty
  2. Используйте новую Microsoft Extensibility Framework, чтобы позволить View Engine быть расширенным
  3. Создайте подробный пример приложения, используя новый View Engine

Я начал все 3 гола, но я стараюсь быть более сфокусированным и заканчиваю их один за другим.

Реализация оператора If

Я реализовал довольно много встроенных функций Smarty. Я ходил в довольно одноранговой образом — я просто приступил к реализации функций , которые я мог бы легко понять, покрывая широкий диапазон , чтобы помочь мне понять, что мне нужно поставить к функциям и что они должны вернуться.

Единственной функцией, которую я просто пропустил, была функция If . Я быстро понял, что реализовать эту функцию будет очень сложно. Способ, которым Smarty выполняет оценку операторов If (и почти всех функций), заключается в переводе шаблона в PHP — поскольку PHP — это язык сценариев, который решает вашу проблему. Скомпилированная природа C # делает это очень сложным упражнением. (Имейте в виду, что я не переводю шаблон в код C # — я на самом деле оцениваю шаблон напрямую)

Динамическая оценка выражения в C #

Давайте посмотрим на типичное утверждение If в Smarty.

{if $person.Name eq 'Fred'}
    <p>Hello Fred!</p>
{elseif $person.Age > 25}
    <p>You're old, {$person.Name}</p>
{/if}

Насколько я знаю, у нас есть два решения этой проблемы в C # 3.5 (новый динамический материал, который будет представлен в C # 4.0, надеюсь, решит это очень элегантным образом). 

Этот первый вариант — создать код для класса, который оценивает данное выражение, скомпилировать его и вызвать скомпилированный код. Наиболее близким к этому я мог найти решение C # REPL . Мое основное беспокойство в связи с этим подходом — производительность — оценка шаблонов должна происходить как можно быстрее. Любой View Engine с низкой производительностью не будет использоваться никем — независимо от того, насколько хороши функции.

Второй вариант — использовать Dynamic LINQ.

Динамический LINQ

Быстрый Google на Dynamic LINQ, вероятно, приведет вас к этому сообщению Скотт Гу . Я посмотрел на динамическую библиотеку запросов, представленную там, и это именно то, что я ищу. Документация, включенная в библиотеку, также превосходна.

Вот один из модульных тестов, которые я написал, чтобы справиться с Dynamic LINQ.

[Test]
public void ShouldParseBooleanStatementWithParameters()
{
    var x = Expression.Parameter(typeof(int), "x");

    var expression = DynamicExpression.ParseLambda(new[] { x }, typeof(bool), "5 == x");

    var compiled = expression.Compile();

    var result = (bool)compiled.DynamicInvoke(5);

    Assert.IsTrue(result);
}

Я также быстро понял, что могу использовать этот же механизм для вычисления отдельных выражений, например:

<li>{$person.Details.Age}</li>

Ранее я вручную вычислял выражение, используя некоторые хитрые размышления — Dynamic LINQ делает это простым упражнением. Вам просто нужно передать значение null как ResultType лямбда-выражения.

Заключение

Я был приятно удивлен тем, как легко использовать Dynamic LINQ. Первоначально я думал, что оценка выражений потребует большого объема работы или что я должен наложить серьезные ограничения на то, что вы можете делать внутри выражений. Dynamic LINQ (и особенно Dynamic LINQ Library) делает это очень простым.

Я включил модульные тесты, которые я использовал для оценки динамической библиотеки LINQ

Author: admin