Expression Lambda avec contient ne fonctionne pas

c# expression-trees lambda linq

Question

Je suis nouveau dans Lambda Expressions et j'ai des problèmes pour obtenir le résultat souhaité. Plus précisément, je ne parviens pas à obtenir que le LINQ contienne une partie de l'expression lambda correcte.

Voici ce que j'ai jusqu'à présent:

// The following line is what I want for my Final Result
var distinctValues = db.Equipment.Where(m => m.Model != null && m.Model.Contains(SearchTerm)).Select(m => m.Model).Distinct().ToList();

var queryableData = db.Equipment.AsQueryable();

var parameterExpression = Expression.Parameter(typeof(Equipment), Column);
var constant = Expression.Constant(null);

var property = Expression.Property(parameterExpression, Column);
var expression1 = Expression.NotEqual(property, constant);
var expression2 = Expression.Equal(property,constant);

Expression callContains = Expression.Call(typeof(Queryable), "Contains", new[] { <string> } );

var lambda1 = Expression.Lambda<Func<Equipment, bool>>(expression1, parameterExpression);
var lambda2 = Expression.Lambda<Func<Equipment, string>>(property, parameterExpression);
var lambda3 = Expression.Lambda<Func<Equipment, bool>>(callContains, parameterExpression);
var compiledLambda1 = lambda1.Compile();
var compiledLambda2 = lambda2.Compile();

Je transmets une propriété et un terme de recherche et je souhaite générer l'équivalent de la requête LINQ ci-dessus sous la forme d'une expression Lambda commençant par "var distinctValues". J'ai des problèmes avec la ligne qui commence par "Expression callContains".

Toute aide est très appréciée.

Merci,

Pete

Réponse acceptée

Merci Xanatos. Avec votre aide, j'ai pu résoudre mon problème. Voici la solution finale que j'ai proposée. Juste quelques changements mineurs:

  // m => 
                var parameterExpression = Expression.Parameter(typeof(Equipment), "m");

                // m.Model
                var modelProperty = Expression.Property(parameterExpression, Column);
                // m.Model != null
                var nonNullExpression = Expression.NotEqual(modelProperty, Expression.Constant(null, typeof(string)));

                // SearchTerm
                var searchTermConstant = Expression.Constant(SearchTerm);

                // m.Model.Contains(SearchTerm)
                var containsExpression = Expression.Call(modelProperty, "contains", null, searchTermConstant);

                // m.Model != null && m.Model.Contains(SearchTerm)
                var andExpression = Expression.AndAlso(nonNullExpression, containsExpression);

                var lambda1 = Expression.Lambda<Func<Equipment, string>>(modelProperty, parameterExpression);
                var lambda2 = Expression.Lambda<Func<Equipment, bool>>(andExpression, parameterExpression);

                var compiledLambda1 = lambda1.Compile();
                var compiledLambda2 = lambda2.Compile();

                var distinctValues1 = db.Equipment.Where(compiledLambda2).Select(compiledLambda1).Distinct().ToList();

Premièrement, j'ai utilisé une surcharge différente pour containsExpression. Deuxièmement, je voulais la propriété de modèle en tant que paramètre. En gros, je voulais transmettre une propriété de variable (Column) et un moteur de recherche de variable. C'est tout.


Réponse populaire

Le Contains est string.Contains . Donc, étant donné:

static readonly MethodInfo contains = (from x in typeof(string).GetMethods(BindingFlags.Instance | BindingFlags.Public)
                                       where x.Name == nameof(string.Contains) && !x.IsGenericMethod
                                       let pars = x.GetParameters()
                                       where pars.Length == 1 &&
                                           pars[0].ParameterType == typeof(string)
                                       select x).Single();

alors l'arbre d'expression .Where() est:

static readonly MethodInfo contains = (from x in typeof(string).GetMethods(BindingFlags.Instance | BindingFlags.Public)
                                       where x.Name == nameof(string.Contains) && !x.IsGenericMethod
                                       let pars = x.GetParameters()
                                       where pars.Length == 1 &&
                                           pars[0].ParameterType == typeof(string)
                                       select x).Single();



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi