Wednesday, September 17, 2014

Linq to Expression Trees

MarkdownPad Document

If you are working with expressions trees in .Net, chances are that you have come across the need for inspecting the nodes of the expression tree.

The idea here is to flatten the expression tree into an IEnumerable<Expression>.

/// <summary>
/// Extends the <see cref="Expression"/> class.
/// </summary>
public static class ExpressionExtensions
{
    /// <summary>
    /// Flattens the <paramref name="expression"/> into an <see cref="IEnumerable{T}"/>.
    /// </summary>
    /// <param name="expression">The target <see cref="Expression"/>.</param>
    /// <returns>The <see cref="Expression"/> represented as a list of sub expressions.</returns>
    public static IEnumerable<Expression> AsEnumerable(this Expression expression)
    {
        var flattener = new ExpressionTreeFlattener();
        return flattener.Flatten(expression);
    }

    private class ExpressionTreeFlattener : ExpressionVisitor
    {
        private readonly ICollection<Expression> nodes = new Collection<Expression>();

        public IEnumerable<Expression> Flatten(Expression expression)
        {
            Visit(expression);
            return nodes;
        }

        public override Expression Visit(Expression node)
        {
            nodes.Add(node);
            return base.Visit(node);
        }
    }
}

Now we can take any expression tree and convert it into a list of expressions and just apply Linq to Objects.

Expression<Func<int>> expression = () => 42;
var result = expression.AsEnumerable().FirstOrDefault(e => e is ConstantExpression);
Console.WriteLine(result);

Output:

42  (ConstantExpression)

Happy Linqing!

No comments: