Thursday, March 09, 2006

About schyzophreny, C#3 intelligence and runtime stupidity

On my way toward a flexible application to perform queries on the vast amount of information my trading desk produces everyday, I was delighted to meet with C#3 and Linq functionnalities. Design time I always thought such a transversal approach was needed and I was surprised to remember that I developped a similar API for VB back in the old days :) Now I could have cutting edge Microsoft functionnalities and exceptionnal compiler intelligence working for me. Just think about this :
var queries = new List<IEnumerable>(); var query1 = this.GetCustomerList().Where( p => p.CompanyName.Length == 4); queries.Add(query1);

This simple line declare function, builds a query, infers return type... Also while I was typing it, I benefited from code completion, and if I add tried to assign it to a wrongly typed variable, I would have been warned of such probable mistake.What a great endeavour from a smal code line ! Yeah but as you may see from my code, I am not a business genius. My query does not add a lot of value for the Market Intelligence people in search of which customer is important. They'd probably So I'd like my users to type in their own queries. That way, market intelligence people will build their own queries, managers their have own other set too, and I wont coerce them into my limited imagination. Runtime definition of queries If I want to do this, here is how I could do to make it work :
  • define a langage
  • build a parser to go from string to a tree of command (an expression tree in Linq)
  • build a visitor for this tree to build the code to run using reflection
  • evaluate

Compare this with the ease I add with the previous query building. And with this solution I have lost all the intellisense, and many other prerun features....

Now what has changed from a functionnal point of view? Nothing, I just want to add some queries to my list...

Beside, all the logic I want my to present to my users already exists in the C# compiler.. Although it is very interesting, why would I need to reinvent the wheel? Partial runtime and dynamic compilation The idea is that I want to tag part of my code, the one which define the queries, as being modifiable, until my program really needs it.
var queries = new List<IEnumerable>(); var query1 = this.GetCustomerList().Where( p => p.CompanyName.Length == 4); queries.Add(query1); [userpoint("DefiningQueries")] foreach (var query1 in queries) { ..
If this tag is seen, I want the compiler to validate my code, and to store it as an expression, not compile it. Then, at runtime, I want to be able to make all the variables available at this place in my code known in a reflection-like manner, only this time reflection is not linked to an assembly or a class, but to a location in code. This helps me pre-validate the user input. And I also want to inject code, and compile it in the specific context of that [Userpoint] !
public void AddExpression(string expr) { CompilerError[] ces = Microsoft.CSharp.Compile(expr, this, "DefiningQueries"); var queries = Code.Userpoint("DefiningQueries").getVariable("queries"); queries.MethodCall("Add", new objet[] { ces } ); }
That way, in a first part of the program, I load my general form, and the environment which enables my users to edit their queries. When a query is added, it is actually added as parsed some code to my section. I make full reuse of everything that already exists at the csharp compiler level. So do you think this concept of partial runtime can be useful in other cases?


Post a Comment

<< Home