Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Drzewa wyrażeń reprezentują kod w strukturze danych przypominającej drzewo, gdzie każdy węzeł jest wyrażeniem, na przykład wywołaniem metody lub operacją binarną, taką jak x < y.
Można skompilować i uruchomić kod reprezentowany przez drzewa wyrażeń. Umożliwia to dynamiczną modyfikację kodu wykonywalnego, wykonywanie zapytań LINQ w różnych bazach danych oraz tworzenie zapytań dynamicznych. Aby uzyskać więcej informacji na temat drzew wyrażeń w LINQ, zobacz How to: Use Expression Trees to Build Dynamic Queries (Visual Basic) (Porady: używanie drzew wyrażeń do tworzenia zapytań dynamicznych (Visual Basic).
Drzewa wyrażeń są również używane w środowisku uruchomieniowym języka dynamicznego (DLR) w celu zapewnienia współdziałania języków dynamicznych z programem .NET Framework oraz umożliwienia autorom kompilatora emitowania drzew wyrażeń zamiast wspólnego języka pośredniego (CIL). Aby uzyskać więcej informacji na temat biblioteki DLR, zobacz Dynamic Language Runtime Overview (Omówienie środowiska uruchomieniowego języka dynamicznego).
Kompilator języka C# lub Visual Basic może utworzyć drzewo wyrażeń na podstawie anonimowego wyrażenia lambda lub ręcznie utworzyć drzewa wyrażeń przy użyciu System.Linq.Expressions przestrzeni nazw.
Tworzenie drzew wyrażeń na podstawie wyrażeń lambda
Gdy wyrażenie lambda jest przypisywane do zmiennej typu Expression<TDelegate>, kompilator emituje kod w celu utworzenia drzewa wyrażeń reprezentującego wyrażenie lambda.
Kompilator języka Visual Basic może generować drzewa wyrażeń tylko z wyrażeń lambd (lub lambdów jednowierszowych). Nie może przeanalizować wyrażeń lambda (lub wielowierszowych lambd). Aby uzyskać więcej informacji na temat wyrażeń lambda w Visual Basic, zobacz Wyrażenia lambda.
W poniższych przykładach kodu pokazano, jak kompilator języka Visual Basic utworzy drzewo wyrażeń reprezentujące wyrażenie lambda Function(num) num < 5.
Dim lambda As Expression(Of Func(Of Integer, Boolean)) =
Function(num) num < 5
Tworzenie drzew wyrażeń przy użyciu interfejsu API
Aby utworzyć drzewa wyrażeń przy użyciu interfejsu API, użyj Expression klasy . Ta klasa zawiera statyczne metody fabryczne, które tworzą węzły drzewa wyrażeń określonych typów, na przykład ParameterExpression, które reprezentują zmienną lub parametr, albo MethodCallExpression, które reprezentują wywołanie metody. ParameterExpression, MethodCallExpressioni inne typy specyficzne dla wyrażeń są również zdefiniowane w System.Linq.Expressions przestrzeni nazw. Te typy pochodzą z typu Expressionabstrakcyjnego .
W poniższym przykładzie kodu pokazano, jak utworzyć drzewo wyrażeń reprezentujące wyrażenie Function(num) num < 5 lambda przy użyciu interfejsu 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})
W programie .NET Framework 4 lub nowszym interfejs API drzew wyrażeń obsługuje również przypisania i wyrażenia przepływu sterowania, takie jak pętle, bloki warunkowe i try-catch bloki. Za pomocą interfejsu API można tworzyć drzewa wyrażeń, które są bardziej złożone niż te, które można utworzyć na podstawie wyrażeń lambda przez kompilator języka Visual Basic. W poniższym przykładzie pokazano, jak utworzyć drzewo wyrażeń, które oblicza współczynniki liczby.
' 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.
Aby uzyskać więcej informacji, zobacz Generowanie metod dynamicznych za pomocą drzew wyrażeń w programie Visual Studio 2010, który ma zastosowanie również do nowszych wersji programu Visual Studio.
Analizowanie drzew wyrażeń
W poniższym przykładzie kodu pokazano, jak drzewo wyrażeń reprezentujące wyrażenie lambda Function(num) num < 5 można rozkładać na jego części.
' 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
Niezmienność drzew wyrażeń
Drzewa wyrażeń powinny być niezmienne. Oznacza to, że jeśli chcesz zmodyfikować drzewo wyrażeń, musisz utworzyć nowe drzewo wyrażeń przez skopiowanie istniejącego i zastąpienie węzłów w nim. Aby przejść przez istniejące drzewo wyrażeń, możesz użyć osoby odwiedzającej drzewo wyrażeń. Aby uzyskać więcej informacji, zobacz Porady: modyfikowanie drzew wyrażeń (Visual Basic).
Kompilowanie drzew wyrażeń
Typ Expression<TDelegate> udostępnia metodę Compile , która kompiluje kod reprezentowany przez drzewo wyrażeń do delegata wykonywalnego.
W poniższym przykładzie kodu pokazano, jak skompilować drzewo wyrażeń i uruchomić wynikowy kod.
' 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.
Aby uzyskać więcej informacji, zobacz Porady: wykonywanie drzew wyrażeń (Visual Basic).