Using Expression Trees and Lambda Expressions to perform CAML queries – Part 1

I have a problem.
I live for writing “good looking” and “easy to read” (maintainable) code “despite” using SharePoint as a backend framework. That combination is sometimes not so easy though.
Imagine this example of such an occasion:

I want to be able to write queries to execute in my C# project that uses SharePoint as the backend. SPSiteDataQuery is the prefered option and such a query is constructed using CAML (Collaborative Application Markup Language), a special form of query language used in SharePoint.
The problem with CAML is that it is somewhat hard to understand and maintain. Imagine that I want to find all items that are of a certain type (in SharePoint a content type), i.e. a book in my backend system.

Before going further, here is a list of the other posts in the series:

Let´s continue…
Normally you construct a sort of business layer (some might use a sort of repository in if you use the ideas of domain driven design DDD) with a method that can take a string that is the CAML, something like this:

public static IList<SPListItem> FindAll(string caml)...

When we call that method it looks something like this to find items of a certain content type:

That isn’t a pretty looking peace of code if you ask me, it´s a definite code smell.
Why?
Well, first of all if you aren´t fluent in CAML you won´t have a chance of reading that and understanding it right away. Ok, so this example isn´t very hard but imagine that you had a more complex expression with a couple of ANDs and ORs in it.
Some might say that we could encapsulate the CAML using some like CamlDotNet to construct the query. That´s great, I would respond but the problem is still there though (that is just a more fancy way of constructing CAML). CAML is bad when you would like your code to be easy to read, maintainable, and expressive.

I have for a while looked at LinqToSharePoint to solve this for me but I still had some problems with it. First of all I think it is too large for me, I only want to use something like LINQ (lambda expressions) to ask the questions and then translate them into CAML. LinqToSharePoint is great (and probably will be even greater in 2010) but in this situation it doesn´t quite do the trick. The big advantage with LINQ (and Expression Trees) is that it is a uniform (and easy to read) way to construct a filter (some might call that a query) over a collection of items.

So after reading up on Expression Tree parsing, here´s a list of some of the blog posts I have found:

OK, so now I think I have removed the smell and the code is now again easy to read and maintain.
The issue now is how do I translate an expression tree into CAML? The answer is really quite easy (in theory atleast), you only have to recursively visit the different nodes in the expression tree and translate them into the corrresponding CAML.

Let´s look a the code for the ExpressionToCamlParser.
First of all the parser will have a method called Translate:

Note: You will see that I have “hardcoded” the startingpoint to “Where”. For this example that is fine but feel free to change the implementation to fit your needs. Remember that I will take babysteps here and this is not meant to be a fullblown CAML parser just yet.

I will add the contents of the call to Visit as a childnode to “Where”. The visit method looks like this:

You will notice that I have taken care of calls of type binary (AND, OR, EQ and so on), constants ( == 1), MemberAccess (will come to that), and MethodCalls( .StartWith() and so on). As I pointed out, this is babysteps so it will not work for all types of expression (not yet atleast).

So, I first take case of parsing the node type (code below) and then I will visit (this is the recursion) the left part of the tree and the the right part. Then I will add the left and right to the node that I just parsed. This will take care of the AND or OR that have right and left branches (you will see an example of this later on).

It´s really quite the same as what happens in the binary translation. I visit the left and right subtrees and then I check to see which method is called (and if I can handle that) and lastly a concatination is made.

Ok, now let´s look an how we get the FieldRef and Value out of the expression tree: