Home » » Building a Lambda Expression Tree

Building a Lambda Expression Tree

Linq and Lambda are two important tools for any .Net developer. Anyone who says otherwise simply does not understand them. Not only do they create less code and a readable approach to sets and flow control, but they enable many compile-time validations that were otherwise either impossible or so complex, most of us tended to skipped them. However, Linq is not Lambda.

Linq: there are two syntaxes.

The first is Query syntax:

var _Results = from record in _List 
               where record.Value == 1 
               orderby record.Name 
               select record;

Some people like the above syntax because it reminds them of TSQL. Some people like it because you can literally read it aloud and it tends to be understandable. But some people prefer the second syntax.

The second is Method syntax:

var _Results = _List
               .Where(x => x.Value == 1)
               .OrderBy(x => x.Name);
               .Select(x => x);

In Method syntax we see Lambda for the first time. You cannot have Lambda without the Lambda symbol of “=>”. People pronounce it as “becomes”, “goes to”, “is of”, and “such that”. I just say “Lambda”, but that’s probably because I don’t want to get swatted in the how-do-you-say-it Jihad.

Note: The “Select(x => x)“ in the Method Syntax is unnecessary; I included it to illustrate the symmetry of the two techniques; they are semantically identical. They result in identical MSIL. They have identical runtime execution. Choosing one over the other is purely preference-based.

Lambda: Shorthand and Longhand

Handy Lambda shorthand syntax like “(x => x.Value == 1)” creates a quick predicate. In this simple sample, we have quite a view pieces. More than you might think:

1. We have the Parameter – which is the “x” we use to indicate the item’s instance.
2. We have the Property – which is the “Value” property of the item we will test.
3. We have the Constant – which is the number 1 used in our test.
4. We have the Operator (or Body) – which is the “==” that compares the Property and Constant.

After a little use, shorthand Lambda is easy to read. The syntax is shorthand for the Lambda Expression Tree. The Expression Tree represents the Lambda expression’s components piece-by-piece.

Building Lambda Expression Trees the long way

Expression trees represent code in a tree-like data structure, where each node is an expression, for example, a method call or a binary operation such as x < y. You can compile and run code represented by expression trees. This enables dynamic modification of executable code, the execution of LINQ queries in various databases, and the creation of dynamic queries. http://msdn.microsoft.com/en-us/library/bb397951.aspx

// sample dto
public class Item
{
    public int Value { get; set; }
    public string Name { get; set; }
}
 
static void Main(string[] args)
{
 
    var _List = new List<Item>
    {
        new Item{ Name = "Smith", Value = 3},
        new Item{ Name = "Smith", Value = 2},
        new Item{ Name = "Wesson", Value = 1},
        new Item{ Name = "Wesson", Value = 4},
    }.AsQueryable<Item>();
 
    var _Type = typeof(Item);
 
    #region Where
 
    var _WhereProperty = _Type.GetProperty("Value");
    var _WhereParameter = Expression.Parameter(typeof(Item), "x");
    // (x.Value == 1)
    var _WhereLeft1 = Expression.PropertyOrField
            (_WhereParameter, _WhereProperty.Name);
    var _WhereRight1 = Expression.Constant(1, typeof(int));
    var _WhereBody1 = Expression.Equal(_WhereLeft1, _WhereRight1);
    // (x.Value != 4)
    var _WhereLeft2 = Expression.PropertyOrField
            (_WhereParameter, _WhereProperty.Name);
    var _WhereRight2 = Expression.Constant(4, typeof(int));
    var _WhereBody2 = Expression.NotEqual(_WhereLeft2, _WhereRight2);
    // (x.Value == 1 || (x.Value != 4))
    var _WhereBody = Expression.OrElse(_WhereBody1, _WhereBody2);
    var _WhereLambda = Expression.Lambda<Func<Item, bool>>
            (_WhereBody, _WhereParameter);
    // apply the Where
    _List = _List.Where(_WhereLambda);
 
    #endregion
 
    #region OrderBy
 
    var _OrderByProperty = _Type.GetProperty("Value");
    var _OrderByParameter = Expression.Parameter(typeof(Item), "x");
    // OrderBy(x => x.Value)
    var _OrderByBody = Expression.Property
            (_OrderByParameter, _OrderByProperty.Name);
    // allow the return type to be object instead of Int16
    var _OrderByConverted = Expression.Convert(_OrderByBody, typeof(object));
    var _OrderByLambda = Expression.Lambda<Func<Item, object>>
            (_OrderByConverted, _OrderByParameter);
    // apply the OrderBy
    _List = _List.OrderBy(_OrderByLambda);
 
    #endregion
 
    // display
    _List.ToList<Item>().ForEach(x => Console.WriteLine(x.Value));
 
    // wait
    Console.Read();
}

The resulting tree would be presented in shorthand like this:

var _Results = from record in _List
               where record.Value == 1 || record.Value != 4
               orderby record.Value 
               select record;

or

var _Results = _List
               .Where(x => x.Value == 1 || x.Value != 4)
               .OrderBy(x => x.Value);
               .Select(x => x);

Conclusion

In either case, the longhand Expression Tree gives two things to us: 1) it gives us an under-the-hood view to help us understand the components of an expression. And, 2) it gives us a method by which we can create dynamic Lambda expressions.

PS: Here’s how to perform a GroupBy dynamically: http://stackoverflow.com/questions/7114922/linq-writing-an-extension-method-to-get-the-row-with-maximum-value-for-each-gro/7115421#7115421


0 comments:

Post a Comment

Popular Posts

Powered by Blogger.
.comment-content a {display: none;}