Impossible de convertir cette linq en arbre d'expression dynamique

c# expression expression-trees linq

Question

J'essaie de créer une expression qui utilise FirstOrDefault avec un prédicat sur une expression de IEnumerable<TComparable> mais cela me donne l'erreur suivante: Le paramètre 'o' n'était pas lié à l'expression de requête LINQ to Entities spécifiée.

J'ai une expression linq comme celle-ci:

IEnumerable<string> names = new List<string>() { "abc", "def", "ghi" };
string name = names.FirstOrDefault(o => o.Contains("abc"));

public static Expression FirstOrDefault(this Expression expression, Type collectionValuesType, MethodInfo comparerMethod, string keyword)
{
    MethodInfo firstOrDefaultMethod = typeof(Enumerable).GetMethods()
        .FirstOrDefault(o => o.Name == "FirstOrDefault" && o.GetParameters().Length == 2)
        .MakeGenericMethod(new Type[] { collectionValuesType });


  Type firstOrDefaultDelegateType = typeof(Func<,>).MakeGenericType(collectionValuesType, typeof(bool));
    ParameterExpression firstOrDefaultPredicateParameter = Expression.Parameter(collectionValuesType);


//THIS LINE binds the "o" in (o => o.Contains("abc")) , and it is where I'm stuck with since yesterday!
    MemberExpression firstOrDefaultParameterO = Expression.Property(expression, typeof(string).GetProperty(???)); 

//o => o.ComparerMethod(keyword)
MethodCallExpression firstOrDefaultCompareExpression = Expression.Call(
    firstOrDefaultParameterO,
    comparerMethod,
    Expression.Constant(keyword, typeof(string))
);

//expression.FirstOrDefault(firstOrDefaultCompareExpression);
return Expression.Call(
    firstOrDefaultMethod,
    expression,
    Expression.Lambda(firstOrDefaultDelegateType, firstOrDefaultCompareExpression, Expression.Parameter(collectionValuesType))
);
}

Si j'avais un type complexe j'utiliserais comme ceci:

public class Example { public string Name; }

//o => o.Name.Contains("abc"))
        MemberExpression firstOrDefaultParameterO = Expression.Property(expression, typeof(Example).GetProperty("Name")); 

Le problème est que je ne sais pas comment lier le type de chaîne, car il ne possède pas de propriété qui donnera la valeur à la propriété.

BTW: collectionValuesType = typeof (chaîne)

J'ai modifié la question comme suggéré pour clarifier les choses.

Réponse acceptée

Vous n'avez pas besoin de construire Expression.Property pour les types simples tels que string.

Par exemple. Si je dois construire l'arborescence d'expression pour la méthode OrderBy pour le type Person avec la propriété Name , je construirai l'arborescence d'expression comme suit:

ParameterExpression pe = System.Linq.Expressions.Expression.Parameter(typeof(T), "p");
Expression<Func<T, TPropertyType>> expr = System.Linq.Expressions.Expression.Lambda<Func<T, TPropertyType>>(System.Linq.Expressions.Expression.Property(pe, propertyName), pe);

Mais pour le type de chaîne, je vais simplement faire: (Puisque votre expression sera simplement x => x pour les types de chaîne)

If( typeof(T)==typeof(string))
{
    ParameterExpression pe = System.Linq.Expressions.Expression.Parameter(typeof(T), "p");
    Expression<Func<T, TPropertyType>> expr = System.Linq.Expressions.Expression.Lambda<Func<T, TPropertyType>>(pe,pe);
}

Vous pouvez probablement utiliser le même concept pour résoudre votre problème.


Réponse populaire

OMG, une journée entière a été perdue parce que je passais le mauvais paramètre dans Expression.Call à la fin.

return Expression.Call(
    firstOrDefaultMethod,
    expression,
    Expression.Lambda(firstOrDefaultDelegateType, firstOrDefaultCompareExpression, 

//THIS IS THE PROBLEM, it should be "firstOrDefaultPredicateParameter"
Expression.Parameter(collectionValuesType))
        );

@ANewGuyInTown Merci pour votre aide. Après avoir examiné votre réponse, j'ai effectué une "analyse complète" dans mon code et constaté cette erreur.



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