Expression Trees


The extension methods you’ve seen so far require a delegate type as parameter; this way, a lambda expression can be assigned to the parameter. Lambda expressions can also be assigned to parameters of type Expression<T>. The type Expression<T> specifies that an expression tree made from the lambda expression is stored in the assembly. This way the expression can be analyzed during runtime and optimized for doing the query to the data source.

Let’s turn to a query expression that was already used previously:

 var brazilRacers = from r in racers                    where r.Country == "Brazil"                    orderby r.Wins                    select r;

This query expression is using the extension methods Where, OrderBy, and Select. The Sequence class defines the Where extension method with the delegate type Func<T, bool> as parameter predicate.

 public static IEnumerable<T> Where<T> (this IEnumerable<T> source,                                        Func<T,bool> predicate);

This way, the lambda expression is assigned to the predicate. Here, the lambda expression is similar to an anonymous method as was explained earlier.

 Func<T, bool> predicate = r.Country == "Brazil";

The Sequence class is not the only class to define the Where extension method. The Where() extension method is also defined by the class Queryable<T>. This class has a different definition of the Where() extension method:

 public static IQueryable<T> Where<T> (this IQueryable<T> source,                                        Expression<Func<T,bool>> predicate);

Here, the lambda expression is assigned to the type Expression<T>, which behaves differently:

 Expression<Func<T, bool>> predicate = r.Country == "Brazil";

Instead of using delegates, the compiler emits an expression tree to the assembly. The expression tree can be read during runtime. Expression trees are built from classes that are derived from the abstract base class Expression. The Expression class is not the same as Expression<T>. Some of the expression classes that inherit from Expression are BinaryExpression, ConstantExpression, InvocationExpression, LambdaExpression, NewExpression, NewArrayExpression, TernaryExpression, UnaryExpression, and so on. The compiler creates an expression tree resulting from the lambda expression.

For example, the lambda expression r.Country == “Brazil” makes use of ParameterExpression, MemberExpression, ConstantExpression, and MethodCallExpression to create a tree and store the tree in the assembly. This tree is then used during runtime to create an optimized query to the underlying data source.

One example where the Expression<T> type is used is with LINQ to SQL. LINQ to SQL defines extension methods with Expression<T> parameters. This way the LINQ provider accessing the database can create a runtime-optimized query to get the data from the database.




Professional C# 2005 with .NET 3.0
Professional C# 2005 with .NET 3.0
ISBN: 470124725
EAN: N/A
Year: 2007
Pages: 427

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net