Création d'un arbre d'expression pour string.Contains

.net-4.0 c# expression-trees

Question

J'ai du mal à créer un arbre d'expression afin de pouvoir filtrer de manière dynamique certaines données.

Je suis venu avec cela, mais il échoue à la var lambda = ligne

foreach (var rule in request.Where.Rules)
{
    var parameterExpression = Expression.Parameter(typeof(string), rule.Field);
    var left = Expression.Call(parameterExpression, typeof(string).GetMethod("ToLower", Type.EmptyTypes));
    var right = Expression.Constant(rule.Data.ToLower());
    var method = typeof(string).GetMethod("Contains", new [] { typeof(string) });
    var call = Expression.Call(left, method, right);
    var lambda = Expression.Lambda<Func<T, bool>>(call, parameterExpression);
    query = query.Where(lambda);
}

La rule var a un champ (ex "Nom") que je souhaite comparer au texte de la rule.Data (ex "tom"). Donc, si T.Name.Contains("tom"); Je veux que la requête inclue l'enregistrement, sinon, pas.

La query var est de type IQueryable<T>

EDIT : Enfin obtenu le travail avec ce code:

foreach (var rule in request.Where.Rules)
{
    var parameter = Expression.Parameter(typeof(T), "x");
    var property = Expression.Property(parameter, rule.Field);
    var value = Expression.Constant(rule.Data);
    var type = value.Type; 
    var containsmethod = type.GetMethod("Contains", new[] { typeof(string) });
    var call = Expression.Call(property, containsmethod, value);
    var lambda = Expression.Lambda<Func<T, bool>>(call, parameter);
    query = query.Where(lambda);
}

Réponse acceptée

Vous y êtes presque, mais votre expression de paramètre doit être de type T , et non de String . Il manque également l'expression qui obtient la propriété du type T comme nom.

Qu'est-ce que vous devriez approximativement avoir ceci

val -> Expression.Constant(typeof(string), rule.Field)
parameter -> Expression.Parameter(typeof(T), "p")
property -> Expression.Property(parameter, "PropertyName")
contains -> Expression.Call(property, containsmethod, val)
equals true -> Expression.True or equals, something like that

Je suis libre de tout cela, il est donc probablement un peu différent d'être valide. L'expression résultante devrait être quelque chose comme ceci

p => p.Name.Contains(val)

Réponse populaire

Si vous voulez créer une requête Where , vous devez créer lambda puis appeler Where sur requête et transmettre lambda . Essaye ça:

Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(call, parameter);
MethodCallExpression expression = Expression.Call(typeof(Queryable), "Where",
                                    new[] { typeof(T) }, query.Expression, lambda);
query = query.Provider.CreateQuery<T>(expression);

au lieu de

var result = Expression.IsTrue(call);
query = query.Provider.CreateQuery<T>(result);


Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow