Ich habe ein bisschen eine Herausforderung, wo ich einen Ausdrucksbaum erstellen muss, um eine Abfrage durch den Benutzer eingegeben darzustellen. Da ich nicht die Zeit habe, alle möglichen Fälle von Benutzereingaben zu erstellen, dachte ich, dass Ausdrucksbäume mir helfen würden, dies zu lösen.Ausdruck gegen Prädikat Probleme
Zum größten Teil hat es. Ich bin jedoch ein wenig ratlos. Ich bin in dem folgenden Code, der versucht, eine List.Find mit einem dynamisch erstellten Ausdruck auszuführen. Der Ausdruck, kurz gesagt, ist dies:
list.Find(m => m.ListOfStrings.Exists(s => s == "cookie"));
wo m
class MyClass
{
public List<string> ListOfStrings { get; set; }
}
ist die ich bisher bekommen habe als
s => s == "cookie"
mit Ausdrücken zu erstellen, kein Problem. Ich habe auch erklärt, eine Method für Exists
var existsMethod = typeof(MyClass)
.GetProperty("ListOfStrings")
.PropertyType
.GetMethod("Exists");
Das einzige Problem, das ich habe, einen Ausdruck zu schaffen wie so
var findLambda = Expression.Lambda(
Expression.Call(
Expression.Property(
Expression.Parameter(typeof(MyClass), "m"),
typeof(MyClass).GetProperty("ListOfStrings")),
existsMethod,
existsLambda),
Expression.Parameter(
typeof (MyClass),
"m"));
mit dem Lambda als Parameter die Methode aufzurufen Es gibt eine verständliche Ausnahme, dass
Expression of type 'System.Func`2[System.String,System.Boolean]' cannot be used for parameter of type 'System.Predicate`1[System.String]' of method 'Boolean Exists(System.Predicate`1[System.String])'
Wie zum Teufel kann ich das überwinden?
Voll Code:
private class MyClass
{
public List<string> ListOfStrings { get; set; }
}
public void SomeMethod()
{
var myObject = new MyClass();
myObject.ListOfStrings = new List<string>();
myObject.ListOfStrings.Add("cookie");
myObject.ListOfStrings.Add("biscuit");
List<MyClass> list = new List<MyClass>();
list.Add(myObject);
var existsLambda = Expression.Lambda(
Expression.Equal(
Expression.Parameter(typeof(string), "s"),
Expression.Constant("cookie")),
Expression.Parameter(typeof(string), "s"));
var existsMethod = typeof(MyClass).GetProperty("ListOfStrings").PropertyType.GetMethod("Exists");
var findLambda = Expression.Lambda(
Expression.Call(
Expression.Property(
Expression.Parameter(typeof(MyClass), "m"),
typeof(MyClass).GetProperty("ListOfStrings")),
existsMethod,
existsLambda),
Expression.Parameter(
typeof (MyClass),
"m"));
list.Find((Predicate<MyClass>)findLambda.Compile());
}
Ich weiß, dass ‚dynamische‘ Benutzereingabe ein bisschen eine Herausforderung in Linq, aber wenn der Benutzer Gibt nur unterschiedliche Werte für ein zu filterndes Feld oder verschiedene Filter für dasselbe Element an. Sie können einfach Where-Klauseln an den ursprünglichen Filter anhängen und die Eingabe im Filter selbst verwenden. Kurz gesagt: Es ist völlig unklar, warum Sie all diese Probleme durchmachen und warum Sie Where-Klauseln nicht anhängen können, wenn es nötig ist. –
@Frans, weil ich den Benutzer nicht einfach verschiedene Werte für ein statisch definiertes Feld angeben lassen kann. Ich brauche eine vollständig dynamische Lösung, um a) die Menge an Code zu reduzieren, die gepflegt werden muss, und c) unter all dem eine Erweiterbarkeit mit neuen Klassen in der Klassenbibliothek anzubieten. –