2010-08-06 7 views
1

Étant donné ce code:Linq Func/Expression d'évaluation locale

 int min = 0; 

     Expression<Func<List<IUser>, bool>> ulContainsJohn = 
        (l => l.Where(u => u.FirstName == "John").Count() > min); 

     Assert.AreEqual(true, ulContainsJohn.Compile()(userList)); 

     min = 3; 

     Assert.AreEqual(true, ulContainsJohn.Compile()(userList)); 

La liste contient 1 "John", mais le second assert échoue. Comment lier la valeur de min au Func avec impatience, de sorte qu'il n'essaie pas de réévaluer la variable min? Clarification: Je ne veux pas changer la signature. Je veux que l'arbre d'expression n'évalue pas min comme une variable, mais comme une expression constante. Existe-t-il de toute façon de convertir l'évaluation de min pour que l'arbre ait une expression constante au lieu d'une évaluation variable?

+0

Pourquoi? Essayez-vous d'analyser l'arbre d'expression? – SLaks

+0

Vous avez un paradoxe ... Vous voulez une expression constante ... mais votre test la change? – Nix

+0

Je veux la valeur de min liée comme une expression constante dans la fonction ulContainsJohn. min peut changer, la valeur liée dans la fonction ne devrait pas. Cela a-t-il un sens maintenant? – Shlomo

Répondre

1

Edit: lire votre commentaire, essayez un créateur de fonction.

Func<int, Func<List<IUser>, bool>> createFn = (min) => 
    (l) => (l.Count(u => u.FirstName == "John") > min); 

Func<List<IUser>, bool>> contains0 = createFn(0); 

Assert.AreEqual(true, contains0(userList)); 

Func<List<IUser>, bool>> contains3 = createFn(3); 

Assert.AreEqual(true, contains3(userList)); 

Essayez d'utiliser un tableau à 1 élément. Laid, mais ça marche.

var values = new int[] { 0 }; 

Expression<Func<List<IUser>, bool>> ulContainsJohn = 
       (l => l.Where(u => u.FirstName == "John").Count() > values[0]); 

Assert.AreEqual(true, ulContainsJohn.Compile()(userList)); 

values[0] = 3; 

Assert.AreEqual(true, ulContainsJohn.Compile()(userList)); 

Une autre option, mieux:

private int Minimum { get; set; } 

... 

Expression<Func<List<IUser>, bool>> ulContainsJohn = 
      (l => l.Where(u => u.FirstName == "John").Count() > Minimum); 

Func<List<IUser>, bool> fn = ulContainsJohn.Compile(); 
Assert.AreEqual(true, fn(userList)); 

Minimum = 3; 

Assert.AreEqual(true, fn(userList)); 
+0

Assez proche. J'ai besoin de l'arbre d'expression. Merci beaucoup. – Shlomo

0

La solution la plus simple est de faire une variable distincte:

int min = 0; 
    int staticMin = min; 
    Func<List<IUser>, bool> ulContainsJohn = 
       l => l.Where(u => u.FirstName == "John").Count() > staticMin ; 
+0

Veuillez voir la clarification que j'ai ajoutée ... – Shlomo

1

Vous devrez faire un paramètre.

Expression<Func<List<IUser>, int, bool>> ulContainsJohn = 
       (List<IUser> l, int min) => (l.Where(u => u.FirstName == "John").Count() > min); 


    ulContainsJohn.Compile()(userList, min); 
+0

Impossible de modifier la signature. S'il vous plaît voir la clarification que j'ai ajouté. Bonne idée cependant. – Shlomo

+0

Pourquoi ne renvoyez-vous pas le nombre? – Nix