Синтаксический анализ дерева выражений с помощью BinaryExpression AND - PullRequest
2 голосов
/ 21 октября 2010

Я только начинаю изучать деревья выражений.

Насколько я понимаю, хорошо, что они могут быть проанализированы, когда они используются в качестве параметров, например,:

Foo.Bar(x => x.Process == "On" && x.Name == "Goofy")

Но как я могу разобрать выражение, когда внутри находится AND?

Может быть, я все неправильно понял, но тогда я не вижу причины для использования выражений?Сейчас я просмотрел почти сотни веб-сайтов, на которых все пытаются объяснить, что такое дерево выражений, и все они добились успеха, ожидая, что они никогда не объясняли, что это было за использование - за исключением тривиального объяснения «Дерево выражений не скомпилировано…».

Ответы [ 2 ]

1 голос
/ 21 октября 2010

Выражения представляют код в виде дерева.Каждый узел дерева представляет собой часть кода.Например, дерево для тела лямбда-выражения в вашем вопросе выглядит примерно так:

BinaryExpression (AndAlso)
  .Left = BinaryExpression (Equal)
    .Left = MemberExpression (x.Process)
      .Expression = ParameterExpression (x)
      .Member = MemberInfo (Process)
    .Right = ConstantExpression ("On")
  .Right = BinaryExpression (Equal)
    .Left = MemberExpression (x.Name)
      .Expression = ParameterExpression (x)
      .Member = MemberInfo (Name)
    .Right = ConstantExpression ("Goofy")

Как правило, код, представленный выражением, не выполняется и даже не компилируется: он анализируется визвлечь из него некоторую информацию, преобразовать ее в другое выражение или даже сгенерировать нечто совершенно иное (например, запрос SQL в Linq to SQL или Entity Framework).Это не было бы возможно с скомпилированным кодом, потому что не было бы никакого способа проанализировать его (по крайней мере, не легко).

0 голосов
/ 21 октября 2010

Я использовал выражения для создания тривиального предметно-ориентированного языка. Это используется в реальном приложении, где я работаю, поэтому это не игрушечный проект.

Я в основном создал свободный интерфейс, который позволяет мне создавать Predicate<T> делегатов, что-то вроде:

Predicate<MyClass> condition = (new ConditionBuilder()).GreaterThanConst(9)
                                                       .And()
                                                       .LessThanConst(4)
                                                       .ToPredicate();

Каждый метод добавляет соответствующее выражение в текущее дерево. Чем ToPredicate компилирует выражение для делегата.

Метод GreaterThanConst выглядит примерно так:

public ConditionBuilder GreaterThan(object constant)
{
    condition = Expression.GreaterThan(Expression.Parameter(constant.GetType()), Expression.Constant(constant));
    return this;
}

Где condition - член, содержащий дерево, которое строится (выращивается?).

Чтобы разобрать ваше выражение, вам нужно написать что-то вроде:

Expression<Func<YourClass, bool>> expr = x => x.Process == "On" && x.Name == "Goofy";

Тогда вы можете посмотреть через сгенерированное дерево выражений и посмотреть, что там.

...