Wie erstelle ich dynamisch einen Ausdruck & lt; Func & lt; MyClass, bool & gt; & gt; Prädikat von Ausdruck & lt; Func & lt; MyClass, string & gt; & gt;
Ich versuche Anhängen, wo Prädikate und mein Ziel ist, erstellen Sie den gleichen Ausdruck wie:
Services.Where(s => s.Name == "Modules" && s.Namespace == "Namespace");
Ich habe den folgenden code:
Expression<Func<Service,string>> sel1 = s => s.Name;
Expression<Func<Service,string>> sel2 = s => s.Namespace;
var val1 = Expression.Constant("Modules");
var val2 = Expression.Constant("Namespace");
Expression e1 = Expression.Equal(sel1.Body, val1);
Expression e2 = Expression.Equal(sel2.Body, val2);
var andExp = Expression.AndAlso(e1, e2);
ParameterExpression argParam = Expression.Parameter(typeof(string), "s");
var lambda = Expression.Lambda<Func<string, bool>>(andExp, argParam);
Diesem erstellen Sie die folgende Ausgabe:
s => ((s.Name == "Modules") AndAlso (s.Namespace == "Namespace"))
Dies ist jedoch fehlerhaft, da die parameter für Namen und Namespace ist nicht das gleiche. Wenn ich ändern Sie die expression-Auswahl:
Expression<Func<Service,string>> sel2 = srv => srv.Namespace;
Ist die Ausgabe:
s => ((s.Name == "Modules") AndAlso (srv.Namespace == "Namespace"))
Wie kann ich eine gültige expression, die mit der Nutzung von sel1 und sel2?
UPDATE (28 feb 2011)
Ich löste es durch das erstellen invoke-Ausdrücke: Expression.Invoke
also die lambda-Ausdrücke sel1 und sel2 nicht erforderlich, um eine MemberExpression:
Expression<Func<Service,string>> sel1 = s => s.Name;
Expression<Func<Service,string>> sel2 = srv => srv.Namespace;
var val1 = Expression.Constant("Modules");
var val2 = Expression.Constant("Namespace");
Expression<Func<Service, bool>> lambda = m => true;
var modelParameter = lambda.Parameters.First();
//sel1 predicate
{
var invokedExpr = Expression.Invoke(sel1, modelParameter);
var binaryExpression = Expression.Equal(invokedExpr, val1);
lambda = Expression.Lambda<Func<Service, bool>>(Expression.AndAlso(binaryExpression, lambda.Body), lambda.Parameters);
}
//sel2 predicate
{
var invokedExpr = Expression.Invoke(sel2, modelParameter);
var binaryExpression = Expression.Equal(invokedExpr, val2);
lambda = Expression.Lambda<Func<Service, bool>>(Expression.AndAlso(binaryExpression, lambda.Body), lambda.Parameters);
}
InformationsquelleAutor der Frage Torbjörn Hansson | 2011-02-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist schwer zu mischen compiler-generierte Ausdruck Bäume und von hand gemachte, gerade weil diese Art der Sache - Extraktion aus der ParameterExpressions ist schwierig. Also lasst uns von vorne anfangen:
Ein wichtiger Aspekt, den ich geändert habe, ist der Typ übergeben
Expression.Parameter
- es ist sicherlich sieht wie es sein sollte, einService
eher als einestring
.Ich habe da einen Versuch, und es schien zu funktionieren, als ich angerufen habe
lambda.Compile
und ausgeführt, es auf ein paar ProbeService
Objekte...InformationsquelleAutor der Antwort Jon Skeet
Können Sie einen Ausdruck-Baum für nullable-Typen, angenommen, Sie haben eine null-Feld BoardId können Sie erstellen, expression tree dynamisch wie diese
müssen Sie bestimmen zuerst die Eigenschaft type, ob die null-Werte zulässt oder nicht
Code unten erstellen eine Dynamische Struktur Ausdruck für die null-Werte zulässt und Nicht auf null festlegbaren Typen
1 - Diese Lösung wird zuerst überprüft, die Nullable-Wert und generieren den Ausdruck.
Dies ist, Wie Sie feststellen können, ob der Typ null-Werte zulässt. Erstellt habe ich eine extension Methode für diesen Zweck
2 - der zweite Schritt ist, um den Typ überprüfen, ob die Zeichenfolge erstellen Sie dann einen Ausdruck für einen string.
3 - der Dritte Schritt ist zu prüfen, ist-Wert ist keine null-Werte nicht als string erstellen Sie dann einen Ausdruck mit equal
InformationsquelleAutor der Antwort Aamir