C# - Apresentando Expression Trees


  No artigo de hoje vou apresentar o conceito de Expression Trees na linguagem C#.

Continuando o artigo anterior vou apresentar os conceitos relacionados com Expression Trees.

Expression Trees ou árvore de expressões, nada mais são do que expressões organizadas em uma estrutura de dados em forma de árvore, sendo que cada nó em uma árvore de expressão é uma expressão. (Este recurso foi introduzido na versão 3.0 do C#)

Por exemplo, uma árvore de expressão pode ser usada para representar a fórmula matemática x < y, onde x, < e y serão representados como uma expressão e organizados na estrutura da árvore.

Assim, uma Árvore de de expressão é uma representação na memória de uma expressão lambda que contém os elementos reais da consulta, não o resultado da consulta.

A árvore de expressão torna a estrutura da expressão lambda transparente e explícita. Você pode interagir com os dados na árvore de expressão da mesma forma que com qualquer outra estrutura de dados.

Além disso, você também pode converter árvores de expressão em código compilado e executá-lo. Essa transformação permite a modificação dinâmica do código executável, bem como a execução de consultas LINQ em vários bancos de dados e a criação de consultas dinâmicas.

Vamos considerar a Expression isMaiordeIdade_Ex :

Expression<Func<Aluno, bool>> isMaiorDeIdade_Ex = a => a.Idade > 21 && a.Idade < 20;

O compilador vai traduzir esta Expression na seguinte Expression Tree:

Expression.Lambda<Func<Aluno, bool>>(
   Expression.AndAlso(
     Expression.GreaterThan(Expression.Property(pe, "Idade"), Expression.Constant(21, typeof(int))),
      Expression.LessThan(Expression.Property(pe, "Idade"), Expression.Constant(20, typeof(int)))),
new[] { pe });

Vamos ver então como criar uma Expression Tree.

Criando uma Expression

A maneira mais fácil de gerar uma árvore de expressão é criar uma instância do tipo Expression<T>, em que T é um tipo de delegate, e, atribuir uma expressão lambda a essa instância.

Vamos criar um projeto do tipo Console Application no VS 2017 Community.

No projeto Console temos que incluir uma referência ao namespace System.Linq.Expressions;

A seguir no método Main() inclua o código abaixo:

Neste exemplo o compilador C# vai gerar uma árvore de expressão a partir da expressão lambda fornecida conforme mostrado abaixo:

//Cria os parâmetros expression
ParameterExpression num1 = Expression.Parameter(typeof(int), "num1");
ParameterExpression num2 = Expression.Parameter(typeof(int), "num2");     
//Cria os parâmetros expression
ParameterExpression[] parametros = new ParameterExpression[] { num1, num2 };     
//Cria o corpo da expressão ou expression body
BinaryExpression body = Expression.Add(num1, num2);     
//Cria a Expression
Expression<Func<int,int,int>> expression = Expression.Lambda<Func<int,int,int>>(body, parametros);

É isso que ocorre por trás dos panos quando atribuimos uma expressão lambda a uma expression tree.

A classe Expression é usada para criar Expression Trees usando a API do .NET Framework.

A partir da versão 4.0 do .NET Framework a API Expression Trees também oferece suporte a atribuições e controle de fluxo, loops, blocos condicionais e blocos try-catch.

Usando a API, você pode criar árvores de expressão que são mais complexas do que aquelas que podem ser criadas a partir de expressões lambda. Usando a API, o código acima pode ser reescrito assim:

Vamos agora analisar a estrutura de uma Expression Tree.

A estrutura de uma Expression Tree possui 4 propriedades:

  1. Body - O corpo da Expression;
  2. Parameters - Os parâmetros da expressão lambda;
  3. NodeType - O tipo do Nó na árvore;
  4. Type - O tipo da Expression;

 

Com base nisso vejamos a criação de uma Expression Tree para um delegate Func.

Cujo execução nos leva ao resultado que vemos abaixo:

Na próxima parte do artigo veremos como se comportam as consultas LINQ.

Pegue o projeto aqui :  CExpressionTrees.zip

(Disse Jesus) - "Então aparecerá no céu o sinal do Filho do homem; e todas as tribos da terra se lamentarão, e verão o Filho do homem, vindo sobre as nuvens do céu, com poder e grande glória."
Mateus 24:30

Referências:


José Carlos Macoratti