Árvores de Expressão (Visual Basic)

As árvores de expressão representam código numa estrutura de dados semelhante a uma árvore, onde cada nó é uma expressão, por exemplo, uma chamada de método ou uma operação binária como x < y.

Pode compilar e executar código representado por árvores de expressão. Isto permite modificar dinâmicamente o código executável, a execução de consultas LINQ em várias bases de dados, e a criação de consultas dinâmicas. Para obter mais informações sobre a expressão de árvores em LINQ, consulte Como: Use Árvores de Expressão para Construir Consultas Dinâmicas (Visual Basic).

As árvores de expressão também são usadas no tempo dinâmico de execução da linguagem (DLR) para fornecer interoperabilidade entre as línguas dinâmicas e a .NET Framework e para permitir que os autores de compiladores emitam árvores de expressão em vez da linguagem intermédia da Microsoft (MSIL). Para obter mais informações sobre o DLR, consulte a Visão Geral do Tempo de Execução da Linguagem Dinâmica.

Você pode ter o compilador C# ou Visual Basic criar uma árvore de expressão para você com base numa expressão de lambda anónima, ou você pode criar árvores de expressão manualmente usando o espaço de System.Linq.Expressions nome.

Criando árvores de expressão a partir de expressões lambda

Quando uma expressão de lambda é atribuída a uma variável de tipo Expression<TDelegate>, o compilador emite código para construir uma árvore de expressão que representa a expressão lambda.

O compilador Visual Basic só pode gerar árvores de expressão a partir da expressão lambdas (ou lambdas de linha única). Não pode analisar a afirmação de lambdas (ou lambdas multi-linha). Para obter mais informações sobre expressões de lambda em Visual Basic, consulte As Expressões Lambda.

Os seguintes exemplos de código demonstram como fazer com que o compilador Visual Basic crie uma árvore de expressão que represente a expressão Function(num) num < 5lambda.

Dim lambda As Expression(Of Func(Of Integer, Boolean)) =  
    Function(num) num < 5  

Criar árvores de expressão usando a API

Para criar árvores de expressão utilizando a API, use a Expression classe. Esta classe contém métodos de fábrica estáticos que criam nós de árvores de expressão de tipos específicos, por exemplo, ParameterExpressionque representam uma variável ou parâmetro, ou MethodCallExpression, que representa uma chamada de método. ParameterExpression, MethodCallExpressione os outros tipos específicos da expressão também são definidos no espaço de System.Linq.Expressions nomes. Estes tipos derivam do tipo Expressionabstrato.

O exemplo de código que se segue demonstra como criar uma árvore de expressão que representa a expressão Function(num) num < 5 lambda utilizando a API.

' Import the following namespace to your project: System.Linq.Expressions  
  
' Manually build the expression tree for the lambda expression num => num < 5.  
Dim numParam As ParameterExpression = Expression.Parameter(GetType(Integer), "num")  
Dim five As ConstantExpression = Expression.Constant(5, GetType(Integer))  
Dim numLessThanFive As BinaryExpression = Expression.LessThan(numParam, five)  
Dim lambda1 As Expression(Of Func(Of Integer, Boolean)) =  
  Expression.Lambda(Of Func(Of Integer, Boolean))(  
        numLessThanFive,  
        New ParameterExpression() {numParam})  

Em .NET Framework 4 ou posteriormente, a expressão árvores API também suporta atribuições e controle expressões de fluxo, tais como loops, blocos condicional e try-catch blocos. Ao utilizar a API, pode criar árvores de expressão mais complexas do que aquelas que podem ser criadas a partir de expressões de lambda pelo compilador Visual Basic. O exemplo a seguir demonstra como criar uma árvore de expressão que calcula o fatorial de um número.

' Creating a parameter expression.  
Dim value As ParameterExpression =  
    Expression.Parameter(GetType(Integer), "value")  
  
' Creating an expression to hold a local variable.
Dim result As ParameterExpression =  
    Expression.Parameter(GetType(Integer), "result")  
  
' Creating a label to jump to from a loop.  
Dim label As LabelTarget = Expression.Label(GetType(Integer))  
  
' Creating a method body.  
Dim block As BlockExpression = Expression.Block(  
    New ParameterExpression() {result},  
    Expression.Assign(result, Expression.Constant(1)),  
    Expression.Loop(  
        Expression.IfThenElse(  
            Expression.GreaterThan(value, Expression.Constant(1)),  
            Expression.MultiplyAssign(result,  
                Expression.PostDecrementAssign(value)),  
            Expression.Break(label, result)  
        ),  
        label  
    )  
)  
  
' Compile an expression tree and return a delegate.  
Dim factorial As Integer =  
    Expression.Lambda(Of Func(Of Integer, Integer))(block, value).Compile()(5)  
  
Console.WriteLine(factorial)  
' Prints 120.  

Para obter mais informações, consulte Generating Dynamic Methods with Expression Trees em Visual Studio 2010, que também se aplica a versões posteriores de Visual Studio.

Árvores de expressão de parsing

O exemplo de código que se segue demonstra como a expressão árvore que representa a expressão Function(num) num < 5 lambda pode ser decomposta nas suas partes.

' Import the following namespace to your project: System.Linq.Expressions  
  
' Create an expression tree.  
Dim exprTree As Expression(Of Func(Of Integer, Boolean)) = Function(num) num < 5  
  
' Decompose the expression tree.  
Dim param As ParameterExpression = exprTree.Parameters(0)  
Dim operation As BinaryExpression = exprTree.Body  
Dim left As ParameterExpression = operation.Left  
Dim right As ConstantExpression = operation.Right  
  
Console.WriteLine(String.Format("Decomposed expression: {0} => {1} {2} {3}",  
                  param.Name, left.Name, operation.NodeType, right.Value))  
  
' This code produces the following output:  
'  
' Decomposed expression: num => num LessThan 5  

Imutabilidade das Árvores de Expressão

As árvores de expressão devem ser imutáveis. Isto significa que, se quiser modificar uma árvore de expressão, deve construir uma nova árvore de expressão copiando a existente e substituindo os nós nela. Você pode usar um visitante de árvore de expressão para atravessar a árvore de expressão existente. Para obter mais informações, consulte Como: Modificar árvores de expressão (Visual Basic).

Compilação de árvores de expressão

O Expression<TDelegate> tipo fornece o Compile método que compila o código representado por uma árvore de expressão num delegado executável.

O seguinte exemplo de código demonstra como compilar uma árvore de expressão e executar o código resultante.

' Creating an expression tree.  
Dim expr As Expression(Of Func(Of Integer, Boolean)) =  
    Function(num) num < 5  
  
' Compiling the expression tree into a delegate.  
Dim result As Func(Of Integer, Boolean) = expr.Compile()  
  
' Invoking the delegate and writing the result to the console.  
Console.WriteLine(result(4))  
  
' Prints True.  
  
' You can also use simplified syntax  
' to compile and run an expression tree.  
' The following line can replace two previous statements.  
Console.WriteLine(expr.Compile()(4))  
  
' Also prints True.  

Para mais informações, consulte Como: Executar árvores de expressão (Visual Basic).

Ver também