Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
As árvores de expressão representam o código em uma 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
.
Você pode compilar e executar código representado por árvores de expressão. Isso permite a modificação dinâmica do código executável, a execução de consultas LINQ em vários bancos de dados e a criação de consultas dinâmicas. Para obter mais informações sobre árvores de expressão no LINQ, consulte Como usar árvores de expressão para criar consultas dinâmicas (Visual Basic).
As árvores de expressão também são usadas no dynamic language runtime (DLR) para fornecer interoperabilidade entre linguagens dinâmicas e o .NET Framework e para permitir que os escritores do compilador emitam árvores de expressão em vez da linguagem intermediária comum (CIL). Para obter mais informações sobre o DLR, consulte Visão geral do Dynamic Language Runtime.
Você pode fazer com que o compilador C# ou Visual Basic crie uma árvore de expressões para você com base em uma expressão lambda anônima ou você pode criar árvores de expressão manualmente usando o System.Linq.Expressions namespace.
Criando árvores de expressão a partir de expressões do Lambda
Quando uma expressão lambda é atribuída a uma variável do tipo Expression<TDelegate>, o compilador emite código para criar uma árvore de expressão que representa a expressão lambda.
O compilador do Visual Basic pode gerar árvores de expressão somente a partir da expressão lambdas (ou lambdas de linha única). Não consegue analisar lambdas declarativas (ou lambdas de várias linhas). Para obter mais informações sobre expressões lambda no Visual Basic, consulte Expressões lambda.
Os exemplos de código a seguir demonstram como fazer com que o compilador do Visual Basic crie uma árvore de expressão que representa a expressão Function(num) num < 5
lambda.
Dim lambda As Expression(Of Func(Of Integer, Boolean)) =
Function(num) num < 5
Criando árvores de expressão usando a API
Para criar árvores de expressão usando a API, use a Expression classe. Essa classe contém métodos estáticos de fábrica que criam nós de árvore de expressão de tipos específicos, por exemplo, ParameterExpression, que representa uma variável ou parâmetro, ou MethodCallExpression, que representa uma chamada de método. ParameterExpression, MethodCallExpressione os outros tipos específicos de expressão também são definidos no System.Linq.Expressions namespace. Estes tipos derivam do tipo Expressionabstrato .
O exemplo de código a seguir demonstra como criar uma árvore de expressão que representa a expressão Function(num) num < 5
lambda usando 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})
No .NET Framework 4 ou posterior, a API de árvores de expressão também oferece suporte a atribuições e expressões de fluxo de controle, como loops, blocos condicionais e try-catch
blocos. 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 pelo compilador do 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 Gerando métodos dinâmicos com árvores de expressão no Visual Studio 2010, que também se aplica a versões posteriores do Visual Studio.
Analisando árvores de expressão
O exemplo de código a seguir demonstra como a árvore de expressão que representa a expressão Function(num) num < 5
lambda pode ser decomposta em 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. Isso significa que, se você quiser modificar uma árvore de expressão, deverá construir uma nova árvore de expressões copiando a existente e substituindo nós nela. Você pode usar um visitante da árvore de expressões para percorrer a árvore de expressões já existente. Para obter mais informações, consulte Como modificar árvores de expressão (Visual Basic).
Compilando á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 em um delegado executável.
O exemplo de código a seguir 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 obter mais informações, consulte Como executar árvores de expressão (Visual Basic).