Динамический LINQ для универсального объекта (без каких-либо жестко закодированных свойств) - PullRequest
0 голосов
/ 28 ноября 2010

У меня есть универсальный объект, который использует словарь для хранения свойств:

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);

Теперь нам нужно запросить ObjList, чтобы найти определенные записи.Динамический LINQ ( Динамический LINQ (Часть 1. Использование библиотеки динамических запросов LINQ) ) кажется идеальным, но из того, что я вижу, требуется, чтобы объект имел предопределенные свойства.

Мы хотим выполнять запросы вроде:

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

Любой токен (например, Имя, Возраст) должен вызывать «GetValue».Любые предложения?

Очевидно, что оператор where полностью зависит от пользователя и не является фиксированным.

Ответы [ 2 ]

1 голос
/ 29 ноября 2010

В C # 4.0 вы могли бы MyObject реализовать интерфейс IDynamicMetaDataProvider, чтобы маркеры свойств были разрешены в GetValue () и SetValue () соответственно. Динамический LINQ должен работать должным образом.

См. этот пост для примера

1 голос
/ 29 ноября 2010

Источник для метода расширения Dynamic LINQ Where:

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)));
}

Сложной частью является бит DynamicExpression.ParseLambda. Очень быстрый просмотр исходного кода показывает, что код синтаксического анализа включает функцию «ParseMemberAccess», которая, по-видимому, предполагает, что вы могли бы сделать что-то вроде:

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

И, если синтаксический анализатор в настоящее время не позволяет этого, вы можете легко расширить его, чтобы он это сделал.

...