On a generic object, dynamic LINQ (without any hard-coded properties)

c# dynamic-linq generics linq

Question

I have a generic object which uses a dictionary to store the properties:

class MyObject 
{
    Dictionary<string, object> Properties = new Dictionary<string, object>();
    internal GetValue(string name) { return Properties[name]; }
    internal SetValue(string name, object value) { Properties[name] = value; } 
}
MyObject obj1 = New MyObject();
obj1.SetValue("Name", "John");
obj1.SetValue("Age", 23);

MyObject obj2 = New MyObject();
obj2.SetValue("Name", "Mary");
obj2.SetValue("Age", 24);

List<MyObject> ObjList = new List<MyObject>();
ObjList.Add(obj1);
ObjList.Add(obj2);

Now we need to query the ObjList to find certain entries. Dynamic LINQ (Dynamic LINQ (Part 1: Using the LINQ Dynamic Query Library)) seems to be perfect, but from what I can see it requires that the object have pre-defined properties.

We want to do queries like:

ObjList.Where("Name == 'Mary' || Age < 24");

Any token (e.g. Name, Age) should call "GetValue". Any suggestions?

Obviously the where statement is completely up to the user and is not fixed.

1
0
3/6/2015 9:05:13 PM

Accepted Answer

In C# 4.0 you could have your MyObject implement the IDynamicMetaDataProvider interface so that property tokens get resolved to GetValue() and SetValue() respectively. Dynamic LINQ should then work as expected.

See this post for an example

1
11/29/2010 2:30:11 AM

Popular Answer

The source for the Dynamic LINQ extension method Where clause is:

public static IQueryable Where(this IQueryable source, string predicate, params object[] values) {
    if (source == null) throw new ArgumentNullException("source");
    if (predicate == null) throw new ArgumentNullException("predicate");
    LambdaExpression lambda = DynamicExpression.ParseLambda(source.ElementType, typeof(bool), predicate, values);
    return source.Provider.CreateQuery(
        Expression.Call(
            typeof(Queryable), "Where",
            new Type[] { source.ElementType },
            source.Expression, Expression.Quote(lambda)));
}

The complicated part is the DynamicExpression.ParseLambda bit. A very quick look through the source shows that the parsing code includes a "ParseMemberAccess" function which seems to suggest that you might be able to do something like:

ObjList.Where("GetValue('Name') == 'Mary' || GetValue('Age') < 24");

And, if the parser doesn't currently allow that, you could easily extend it so that it does.



Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow