views:

268

answers:

4

This is probably a stupid question, but here goes. I would like to be able to dynamically construct a predicate < T > from a string parsed from a database VARCHAR column, or any string, for that matter. For example, say the column in the database contained the following string:

return e.SomeStringProperty.Contains("foo");

These code/string values would be stored in the database knowing what the possible properties of the generic "e" is, and knowing that they had to return a boolean. Then, in a magical, wonderful, fantasy world, the code could execute without knowing what the predicate was, like:

string predicateCode = GetCodeFromDatabase();
var allItems = new List<SomeObject>{....};
var filteredItems = allItems.FindAll(delegate(SomeObject e) { predicateCode });

or Lambda-ized:

var filteredItems = allItems.FindAll(e => [predicateCode]);

I know it can probably never be this simple, but is there a way, maybe using Reflection.Emit, to create the delegate code dynamically from text and give it to the FindAll < T > (or any other anonymous/extension) method?

+1  A: 

Check out the Dynamic Linq project it does all this and more!

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Great for simple stuff like user selected orderby's or where clauses

TFD
Nice of you to make this community wiki, but I couldn't find anything relating to "Dynamic Link project" to provide some context to your answer. Can you please add a URL?
Michael Meadows
The problem with Dynamic Linq (so far as I can tell) is that I wouldn't be able to use any complex, non-SQL code in the Predicate. The "allItems" list is not a database-bound object, it's a list of strings, actually, that I'd like to be able to test in various ways not defined in the source code.
AJ
That would be Dynamic Linq :-) not Linkhttp://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspxalsohttp://elegantcode.com/2008/04/15/dynamic-linq/
TFD
A: 

It is possible using emit, but you'd be building your own parser.

EDIT

I remember that in ScottGu's PDC keynote, he showed a feature using the CLI version of the .net framework that resembled Ruby's eval, but I can't find a URL that can corroborate this. I'm making this a commnity wiki so that anyone who has a good link can add it.

Michael Meadows
The link you provided isn't for C# 4.0, it's for Mono 2.2.
configurator
You're right. I removed the link and put in the edited comments.
Michael Meadows
+1  A: 

The C# and VB compilers are available from within the .NET Framework:

C# CodeDom Provider

Be aware though, that this way you end up with a separate assembly (which can only be unloaded if it's in a separate AppDomain). This approach is only feasible if you can compile all the predicates you are going to need at once. Otherwise there is too much overhead involved.

System.Reflection.Emit is a great API for dynamically emitting code for the CLR. It is, however, a bit cumbersome to use and you must learn CIL.

LINQ expression trees are an easy to use back-end (compilation to CIL) but you would have to write your own parser.

I suggest you have a look at one of the "dynamic languages" that run on the CLR (or DLR) such as IronPython. It's the most efficient way to implement this feature, if you ask me.

SealedSun
A: 

Hi, i stepped off the dynamic linq because it's limited in ways i want to search a collection, unless you prove me wrong.

my filter needs to be: in a list of orders, filter the list so that i have only the orders with in the collection of items in that order, an item with the name "coca cola"

so that will result to a method of: orders.Findall(o => o.Items.Exists(i => i.Name == "coca cola"))

in dynamic linq I didn't find any way to do that, so i started with CodeDomProvicer. I created a new Type with a method which contains my dynamically built FindAll Method

public static IList Filter(list, searchString) { // this will by dynamically built code return orders.Findall(o => o.Items.Exists(i => i.Name == "coca cola")); }

when i try to build this assembly: CompilerResults results = provider.CompileAssemblyFromSource(parameters, sb.ToString());

I'm getting the error: Invalid expression term ">"

why isnt the compile able to compile the predicate?