I recently read an interesting article that describes how the LINQ to SQL provider was implemented. The article gave a pretty good description of expression trees and how they relate to IQueryable and LINQ. I thought it might be interesting to try and implement my own LINQ provider to gain a better understanding of the LINQ technology.
LINQ to File System
I thought a pretty easy and useful example would be to implement a LINQ provider for the file system – the idea being that you specify a root path and the LINQ provider would allow you to query files and folders within this root path.
There is another very useful walkthrough on MSDN that guides the reader through the different steps for creating a LINQ provider – I used concepts from this article extensively in my implementation.
The first thing we need to do is to write an implementation for the *IQueryable* interface. (In my provider I actually implemented the *IOrderedQueryable* interface, which inherits from *IQueryable*) I also created a *FileSystemElement* class which is basically a wrapper for any file element we query. We will see later on that we can apply filters on any property in this *FileSystemElement* class.
The next step is to implement the IQueryProvider interface – this class is responsible for creating queries and evaluating them. At the lowest level this basically means we need to be able to create queries and then execute them.
So far we haven’t done any real magic – we’re basically using the expression tree created by the compiler and delegating the evaluation of expressions to the FileSystemQueryContext class.
Keep in mind that I don’t really want to manually evaluate expressions – I simply want to retrieve all files and folders from the file system and allow the user to filter on the FileSystemElement class I’m returning. The only real work I want to do is to retrieve the files and folders and wrap them in an *IQueryable* interface.
I also need to copy the expression tree that represents the LINQ query and make a single modification – we simply replace the data source with the concrete list of files and folders.
Luckily the walkthrough on MSDN already provides an implementation of an ExpressionVisitor class – this class basically does all the work for us.
Here is the method where I look for a call to the FileSystemContext class – which I replace with the list of files and folders.
Using the new provider
The following is an example of kind of query we can write with this provider.
Which is actually quite cool. When I started this exercise I thought that it would actually be a lot more work – granted, I’m delegating most of the work to the underlying technology, but still – it was easier than I thought.
By the way, keep in mind I wrote this provider as an example – you would be absolutely nuts to actually write a LINQ provider for this kind of file access. The following code does pretty much the same as my implementation, minus any of the hard work.