Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Los árboles de expresión representan código en una estructura de datos similar a un árbol, donde cada nodo es una expresión, por ejemplo, una llamada de método o una operación binaria como x < y
.
Puede compilar y ejecutar código representado por árboles de expresión. Esto permite la modificación dinámica del código ejecutable, la ejecución de consultas LINQ en varias bases de datos y la creación de consultas dinámicas. Para obtener más información sobre los árboles de expresión en LINQ, vea How to: Use Expression Trees to Build Dynamic Queries (Visual Basic).
Los árboles de expresión también se usan en Dynamic Language Runtime (DLR) para proporcionar interoperabilidad entre los lenguajes dinámicos y .NET Framework y para permitir que los escritores del compilador emitan árboles de expresión en lugar de lenguaje intermedio común (CIL). Para obtener más información sobre el entorno DLR, vea Información general acerca de Dynamic Language Runtime.
Puede hacer que el compilador de C# o Visual Basic cree un árbol de expresiones según una expresión lambda anónima, o bien puede crear árboles de expresión manualmente mediante el System.Linq.Expressions espacio de nombres .
Creación de árboles de expresión a partir de expresiones lambda
Cuando se asigna una expresión lambda a una variable de tipo Expression<TDelegate>, el compilador emite código para crear un árbol de expresión que representa la expresión lambda.
El compilador de Visual Basic solo puede generar árboles de expresión a partir de expresiones lambdas (o lambdas de una sola línea). No pueden analizar lambdas de instrucción (o lambdas de varias líneas). Para obtener más información sobre las expresiones lambda en Visual Basic, vea Expresiones lambda.
En los ejemplos de código siguientes se muestra cómo hacer que el compilador de Visual Basic cree un árbol de expresiones que represente la expresión Function(num) num < 5
lambda .
Dim lambda As Expression(Of Func(Of Integer, Boolean)) =
Function(num) num < 5
Creación de árboles de expresión mediante la API
Para crear árboles de expresión mediante la API, use la Expression clase . Esta clase contiene métodos de fábrica estáticos que crean nodos de árbol de expresiones de tipos específicos, por ejemplo, ParameterExpression, que representa una variable o parámetro, o MethodCallExpression, que representa una llamada al método. ParameterExpression, MethodCallExpressiony los otros tipos específicos de expresiones también se definen en el System.Linq.Expressions espacio de nombres . Estos tipos derivan del tipo Expressionabstracto .
En el ejemplo de código siguiente se muestra cómo crear un árbol de expresiones que represente la expresión Function(num) num < 5
lambda mediante la 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})
En .NET Framework 4 o posterior, la API de árboles de expresión también admite asignaciones y expresiones de flujo de control, como bucles, bloques condicionales y try-catch
bloques. Mediante la API, puede crear árboles de expresión más complejos que los que el compilador de Visual Basic puede crear a partir de expresiones lambda. En el ejemplo siguiente se muestra cómo crear un árbol de expresión que calcula el factorial de un 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 obtener más información, vea Generar métodos dinámicos con árboles de expresión en Visual Studio 2010, que también se aplica a versiones posteriores de Visual Studio.
Análisis de árboles de expresión
En el ejemplo de código siguiente se muestra cómo el árbol de expresiones que representa la expresión Function(num) num < 5
lambda se puede descomponer en sus 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
Inmutabilidad de árboles de expresión
Los árboles de expresión deben ser inmutables. Esto significa que, si desea modificar un árbol de expresiones, debe construir un nuevo árbol de expresiones copiando el existente y reemplazando los nodos en él. Puede usar un visitante de árbol de expresión para recorrer el árbol de expresión existente. Para obtener más información, vea How to: Modify Expression Trees (Visual Basic) (Cómo: Modificar árboles de expresión [Visual Basic]).
Compilar árboles de expresión
El Expression<TDelegate> tipo proporciona el Compile método que compila el código representado por un árbol de expresiones en un delegado ejecutable.
En el ejemplo de código siguiente se muestra cómo compilar un árbol de expresiones y ejecutar el 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 obtener más información, vea How to: Execute Expression Trees (Visual Basic) (Cómo: Ejecutar árboles de expresión [Visual Basic]).