У меня есть небольшая проблема, когда мне нужно создать дерево выражений для представления запроса, введенного пользователем. Поскольку у меня нет времени на создание всех возможных случаев пользовательского ввода, я подумал, что деревья выражений помогут мне в этом решении.
По большей части, это так. Я, однако, немного озадачен. Я в коде ниже, пытаясь выполнить List.Find с динамически созданным выражением. Короче говоря, это выражение:
list.Find(m => m.ListOfStrings.Exists(s => s == "cookie"));
, где m равно
class MyClass
{
public List<string> ListOfStrings { get; set; }
}
Я дошел до того, чтобы создать
s => s == "cookie"
с выражениями, без проблем. Я также объявил methodinfo для Exists
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"));
Это дает понятное исключение, что
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])'
Как, черт возьми, я могу это преодолеть?
Полный код:
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());
}