2008-10-24 12 views
3

J'ai un IQueryable et un objet de type T.Comment construire un arbre d'expression Linq qui se compare à un objet générique?

Je veux faire IQueryable(). Où (o => o.GetProperty (fieldName) == objectOfTypeT.GetProperty (fieldName))

si ...

public IQueryable<T> DoWork<T>(string fieldName) 
     where T : EntityObject 
{ 
    ... 
    T objectOfTypeT = ...; 
    .... 
    return SomeIQueryable<T>().Where(o => o.GetProperty(fieldName) == objectOfTypeT.GetProperty(fieldName)); 
} 

Fyi, GetProperty n'est pas une fonction valide. J'ai besoin de quelque chose qui remplisse cette fonction. Suis-je en train de fondre le cerveau le vendredi après-midi ou est-ce une chose complexe à faire?


objectOfTypeT Je peux faire ce qui suit ...

var matchToValue = Expression.Lambda(ParameterExpression 
.Property(ParameterExpression.Constant(item), "CustomerKey")) 
.Compile().DynamicInvoke(); 

qui fonctionne parfaitement, maintenant je dois juste la deuxième partie.

Où (o = SomeIQueryable() retour>o.GetProperty (fieldName) == matchValue);

Répondre

4

Comme si:

var param = Expression.Parameter(typeof(T), "o"); 
    var fixedItem = Expression.Constant(objectOfTypeT, typeof(T)); 
    var body = Expression.Equal(
     Expression.PropertyOrField(param, fieldName), 
     Expression.PropertyOrField(fixedItem, fieldName)); 
    var lambda = Expression.Lambda<Func<T,bool>>(body,param); 
    return source.Where(lambda); 

J'ai commencé un blog qui couvrira un certain nombre de sujets d'expression, here. Si vous rencontrez des problèmes, une autre option consiste à extraire la valeur de objectOfTypeT en premier (en utilisant la réflexion), puis d'utiliser cette valeur dans le Expression.Constant, mais je suppose que tout ira bien "tel quel".

+0

Parfait. Exactement ce dont j'avais besoin. Maintenant, pour comprendre exactement ce qui se passe :) – JTew

+0

@JTew - l'entrée du blog pourrait faire la lumière ... –

0

D'après ce que je peux voir à ce jour il va devoir être quelque chose comme ...

IQueryable<T>().Where(t => 
MemberExpression.Property(MemberExpression.Constant(t), fieldName) == 
ParameterExpression.Property(ParameterExpression.Constant(item), fieldName)); 

Alors que je peux obtenir ce pour compiler il est pas tout à fait exécuter la façon dont il est nécessaire.

+0

Fermer; vous devez construire une LambdaExpression - voir mon article. –

0

Qu'en est-:

public class Person 
    { 
     public string Name { get; set; } 
     public int Age { get; set; } 

    } 

    public Func<T, TRes> GetPropertyFunc<T, TRes>(string propertyName) 
    { 
     // get the propertyinfo of that property. 
     PropertyInfo propInfo = typeof(T).GetProperty(propertyName); 

     // reference the propertyinfo to get the value directly. 
     return (obj) => { return (TRes)propInfo.GetValue(obj, null); }; 
    } 

    public void Run() 
    { 
     List<Person> personList = new List<Person>(); 

     // fill with some data 
     personList.Add(new Person { Name = "John", Age = 45 }); 
     personList.Add(new Person { Name = "Michael", Age = 31 }); 
     personList.Add(new Person { Name = "Rose", Age = 63 }); 

     // create a lookup functions (should be executed ones) 
     Func<Person, string> GetNameValue = GetPropertyFunc<Person, string>("Name"); 
     Func<Person, int> GetAgeValue = GetPropertyFunc<Person, int>("Age"); 


     // filter the list on name 
     IEnumerable<Person> filteredOnName = personList.Where(item => GetNameValue(item) == "Michael"); 
     // filter the list on age > 35 
     IEnumerable<Person> filteredOnAge = personList.Where(item => GetAgeValue(item) > 35); 
    } 

Ceci est un moyen d'obtenir des valeurs d'une chaîne par des propriétés sans utiliser des requêtes dynamiques. L'inconvénient est que les valeurs al seront encadrées/non boxées.

Questions connexes