2010-11-28 22 views
0

J'ai un objet générique qui utilise un dictionnaire pour stocker les propriétés:LINQ dynamique sur un objet générique (sans propriétés codées en dur)

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

Maintenant, nous avons besoin d'interroger le OBJLIST pour trouver certaines entrées. Dynamic LINQ (Dynamic LINQ (Part 1: Using the LINQ Dynamic Query Library)) semble être parfait, mais d'après ce que je peux voir, il faut que l'objet ait des propriétés prédéfinies.

Nous voulons faire des requêtes telles que:

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

Tout jeton (par exemple Nom, âge) devrait appeler "GetValue". Aucune suggestion?

Évidemment, l'instruction where est complètement à la hauteur de l'utilisateur et n'est pas corrigée.

Répondre

1

En C# 4.0 vous pouvez avoir votre MyObject implémenter l'interface IDynamicMetaDataProvider afin que les jetons de propriété soient résolus à GetValue() et SetValue() respectivement. Le LINQ dynamique devrait alors fonctionner comme prévu.

Voir this post pour un exemple

+0

Wow, merci pour l'indice. En fait, je dirais que je pourrais utiliser un ExpandoObject à la place! –

1

La source de la méthode d'extension dynamique LINQ clause Where est:

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

La partie compliquée est le bit DynamicExpression.ParseLambda. Un look très rapide à travers la source indique que le code d'analyse syntaxique comprend une fonction « ParseMemberAccess » qui semble suggérer que vous pourriez être en mesure de faire quelque chose comme:

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

Et, si l'analyseur ne permet actuellement que , vous pourriez facilement l'étendre afin qu'il le fasse.