Thursday, February 26, 2009 9:06 PMHi,
This may be a long-shot but does anybody know if there is anyway of directly generating a lambda expression (or its corresponding delegate) from a string representaion of the lambda using some of the stuff in System.Linq.Expressions? I have had a good root around and have not found anything yet... For example I would like to produce a delegate from the String (not an actual lambda expression in code):
string lambdaString = "() => a > 5";
Func<bool> d = MagicFunction(lambdaString);
I would like to load these things from file at runtime, so they're not availabe at compile time..
I suppose I could try to write my own parser and then use the various classes and functions in System.Linq.Expressions to build them up myself bit by bit, but the amount of work in this could be huge! It would be nice if there was a function that just did id!
Thanks for Reading...
Ridge Solutions (www.RidgeSolutions.ie)
Thursday, February 26, 2009 9:25 PMModeratorAFAIK there is no function you can call. All the processing is done by the C# compiler. There is no CLR functionality that handles this. The compiler converts the code into regular CLR code (function calls and whatnot). Trying to parse this code yourself is going to result in frustration because any valid C# code can appear within the expression. Don't even get started on the closure aspects of it all.
Note that the example you gave is actually relying on closure so (without the encasing code also being stored as a string) you won't be able to generate code. However you could potentially generate code for an expression that did this: (a) => a > 5
One approach, if you want to go this route, is to use dynamic code generation or the CodeDOM to generate the code for you. To get that to work you'd have to create a class and method that implemented the delegate signature. Within the method you could stuff the string representing the expression (properly generated to allow the compiler to generate the code properly). You could then compile the code down via the C# compiler to an assembly that you can then invoke. To keep things simple you might generate a static method of a static class to hold the expression. You would then call the static method of the class (which in turn calls the lambda expression-generated code). I doubt performance would be great but it'd work I believe. I can't say that I've ever verified that the CodeDOM version of the C# compiler would accept a lambda expression. The CodeDOM itself doesn't support lambda expressions so you'd end up having to pass the string to the DOM as a raw string with some syntactical sugar.
Another approach might be to just take everything to the right of the => and compile that down to code. The signature of the method you generate would contain as parameters anything to the left of the =>. The hard part will be that lambda expressions don't generally contain the type of the parameter so you'll have a hard time figuring that out. That is effectively what the compiler does (minus type inferencing and closure). Everything to the write could be shipped down to the DOM as a string so you don't have to worry about parsing it.
If you just need simple data evaluation then you might also consider using DataBind.Eval or equivalent. That only works with basic expressions but it is a lot easier than trying to deal with lambda expressions.
That's all the ideas I can come up with.
Michael Taylor - 2/26/09
- Marked As Answer by Kevin Godden Friday, February 27, 2009 2:06 PM
Friday, February 27, 2009 2:06 PM
Thanks for your answer - I had suspected that there was no such magical function! This is really just a bit of hobby for me, so I won't be heartbroken if I can get it to work, however I find the whole are very interesting so I will probably follow up on your suggestions.
I have been thinking about your point on Closure, I want all the delegates produced to be of the same arity, but at the same time want the expressions to be able to pull in data from multiple sources so maybe what I could do is pass in a 'context' object as the one and only parameter and allow the expressions to retrieve the data they need from this, something like: (context) => context.a > 5 && context.b < 3
I will have a look at CodeDOM - lookes very promising, a change of tack along these lines may be more productive!
Just a thought, maybe I would be better off storing Java Script (or similar) snippets instead and evaluating along the lines of http://www.west-wind.com/WebLog/posts/10688.aspx
Thanks again for the pointers
Ridge Solutions (www.RidgeSolutions.ie)
Monday, April 13, 2009 8:09 AMHi,
let me propose a very similar solution: dynamicLinq which provides support for dynamic construction of filter expressions from strings. It's open source and contains a parser which seems useful to your problem with slight modifications.