Diese Linq kann nicht in dynamische Ausdrucksstruktur konvertiert werden

c# expression expression-trees linq

Frage

Ich versuche, einen Ausdruck zu erstellen, der FirstOrDefault mit Prädikat für einen Ausdruck von IEnumerable<TComparable> aber es gibt mir diesen Fehler: Der Parameter 'O' wurde nicht in dem angegebenen LINQ to Entities-Abfrageausdruck gebunden

Ich habe einen linq Ausdruck wie folgt:

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))
);
}

Wenn ich einen komplexen Typ hätte, würde ich folgendes verwenden:

public class Example { public string Name; }

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

Das Problem ist, dass ich nicht weiß, wie String-Typ gebunden wird, da es keine Eigenschaft hat, die den Eigenschaftswert geben wird.

BTW: collectionValuesType = typeof (Zeichenfolge)

Ich habe die Frage wie vorgeschlagen bearbeitet, um die Dinge klarzustellen.

Akzeptierte Antwort

Sie müssen die Expression.Property für einfache Typen wie string nicht erstellen.

Beispielsweise. Wenn ich den Ausdrucksbaum für die OrderBy-Methode für den Typ Person mit Name Eigenschaft erstellen muss, erstelle ich den Ausdrucksbaum wie folgt:

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);

Aber für String-Typ werde ich einfach tun: (Da Ihr Ausdruck wird einfach x => x für String-Typen)

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);
}

Sie können wahrscheinlich das gleiche Konzept verwenden, um Ihr Problem zu beheben.


Beliebte Antwort

OMG, einen ganzen Tag verloren, weil ich am Ende den falschen Parameter am Expression.Call übergeben habe.

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

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

@ANewGuyInTown Danke für deine Hilfe, nachdem ich deine Antwort angesehen habe, habe ich einen "vollständigen Scan" in meinem Code durchgeführt und diesen Fehler gefunden



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum