C#
Summary - Expression trees
Combine Expression and Compile to write a dynamic filter builder.
Summary - Expression trees
In this group you learned Expression<T>, lambda conversion, body inspection, Compile and IQueryable. You can convert a lambda to an expression tree, inspect it and turn it back into a delegate with Compile.
Now you will combine these to write a dynamic filter builder: first build an n > 10 expression tree by hand, then compile it and run it over an array.
Exercise Build a dynamic filter and invoke it
Build an n > 10 condition as an expression tree. Steps: ParameterExpression pe = Expression.Parameter(typeof(int), "n");, Expression body = Expression.GreaterThan(pe, Expression.Constant(10));, Expression<Func<int, bool>> filter = Expression.Lambda<Func<int, bool>>(body, pe);. Then build a delegate with Func<int, bool> fn = filter.Compile(); and print Console.WriteLine(fn(15));.
Show example solution
ParameterExpression pe = Expression.Parameter(typeof(int), "n"); Expression body = Expression.GreaterThan(pe, Expression.Constant(10)); Expression<Func<int, bool>> filter = Expression.Lambda<Func<int, bool>>(body, pe); Func<int, bool> fn = filter.Compile(); Console.WriteLine(fn(15));
Example solution:
using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
ParameterExpression pe = Expression.Parameter(typeof(int), "n");
Expression body = Expression.GreaterThan(pe, Expression.Constant(10));
Expression<Func<int, bool>> filter = Expression.Lambda<Func<int, bool>>(body, pe);
Func<int, bool> fn = filter.Compile();
Console.WriteLine(fn(15));
}
}
Exercise Apply the dynamic filter to an array
Build an n > 10 filter as an expression tree, produce a delegate with filter.Compile() and apply it to { 5, 12, 8, 20, 3 } with numbers.Where(fn). Iterate with foreach and print each element with Console.WriteLine(n).
Show example solution
ParameterExpression pe = Expression.Parameter(typeof(int), "n"); Expression body = Expression.GreaterThan(pe, Expression.Constant(10)); Expression<Func<int, bool>> filter = Expression.Lambda<Func<int, bool>>(body, pe); Func<int, bool> fn = filter.Compile(); var filtered = numbers.Where(fn); foreach (var n in filtered) { Console.WriteLine(n); }
Example solution:
using System;
using System.Linq;
using System.Linq.Expressions;
class Program
{
static void Main()
{
int[] numbers = { 5, 12, 8, 20, 3 };
ParameterExpression pe = Expression.Parameter(typeof(int), "n");
Expression body = Expression.GreaterThan(pe, Expression.Constant(10));
Expression<Func<int, bool>> filter = Expression.Lambda<Func<int, bool>>(body, pe);
Func<int, bool> fn = filter.Compile();
var filtered = numbers.Where(fn);
foreach (var n in filtered)
{
Console.WriteLine(n);
}
}
}
Test yourself
-
What does Compile return?
- An expression tree
- A runnable delegate
- A Type object
- A string
Show answer
A runnable delegate — Correct. Compile returns a runnable delegate.
-
Match the property to its content
- Body
- Inner expression
- NodeType
- Operation kind
- Parameters
- Parameter list
- Compile
- Produces a delegate
Next lesson: The Type class