Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
As árvores de expressão representam código em uma estrutura de dados semelhante a uma árvore, em que 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 DLR (Dynamic Language Runtime) para fornecer interoperabilidade entre linguagens dinâmicas e o .NET Framework e para permitir que os gravadores do compilador emitam árvores de expressão em vez de CIL (linguagem intermediária comum). Para obter mais informações sobre a 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ão para você com base em uma expressão lambda anônima ou crie árvores de expressão manualmente usando o System.Linq.Expressions namespace.
Criando árvores de expressão a partir de expressões Lambda
Quando uma expressão lambda é atribuída a uma variável de tipo Expression<TDelegate>, o compilador emite o 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 de lambdas de expressão (ou lambdas de linha única). Ele não é possível analisar instruções lambdas (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 represente a expressão Function(num) num < 5lambda.
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 de fábrica estáticos que criam nós de árvore de expressão de tipos específicos, por exemplo, ParameterExpressionque 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. Esses 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 dá 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 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 lambda Function(num) num < 5 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 de á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ão copiando a existente e substituindo nós nela. Você pode usar um visitantes de árvore expressão para percorrer a árvore de expressão 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).