It is with great pleasure that I announce yet another flavor of LINQ – MetaLinq – the ability to query over and edit expression trees using LINQ.
Why MetaLinq? Well, Oren Novotny, who is working on yet another project, SLINQ, aka Linq to Streams, and who also has contributed to i4o, was asking me if I knew an mechanism where one could walk an expression tree and replace certain nodes. Being the sort of person who always like a challenge, I decided to help, creating an enumerator extension method for Expressions that allows you to easily walk the expression tree, with the plan of editing the nodes in the tree as I go along (i.e. using a LINQ query over the resulting "walk the tree" enumeration). Then it hit me. Expression trees are immutable. I find this by not reading stuff online, but hacking away and finding all those darn properties of expression nodes are read only.
Damn. How to get around this one?
Well, after reading Jomo Fisher’s blog, it became evident that if you want to get a variation of a tree, you have to copy part, or all, of the tree, and carefully replace the parts you want changed as you are doing so. Thankfully, Jomo put a reasonable approach up on his blog, which uses a visitor pattern and does a selective replacement. And his method works.
That said, I decided to take a different approach. ExpressionBuilder, which is part of MetaLinq for the moment, is the result. The ExpressionBuilder namespace allows you to create an Editable Shadow of an expression tree, modify it in place, and then by calling ToExpression on the shadow tree, generate a new, normal, immutable tree. It has a class, EditableExpression, that has a factory method (CreateEditableExpression) that takes any expression, and returns an EditableExpression that mirrors the immutable Expression.
For example, to get the editable tree, you would do this to get an editable copy:
Expression immutable = someExpression; //you can’t change immutable directly
EditableExpression mutable = EditableExpression.CreateEditableExpression(immutable);
//..then do this to convert it back
Expression newCopy = mutable.ToExpression;
//pretend there are parens after ToExpression - shortcoming in my blog software that does not allow me to say ToExpression with parens afterwards
In other words, you can now edit expression trees. ExpressionBuilder is to Expressions what StringBuilder is to Strings.
I will warn you that you can easily shoot yourself in the foot with this. As of the current version, you can easily create a cyclic graph, which, of course, will create an infinite loop when you try to convert it back into an immutable expression. While I will be adding code to check for cycles in the future, there is no getting around that having full edit capability on the expression tree can cause subtle bugs.