我有一点挑战,我必须创建一个表达式树来表示用户的查询输入。由于我没有时间创建所有可能的用户输入案例,我认为表达式树会帮助我解决这个问题。
在大多数情况下,它有。然而,我有点难过。我在下面的代码中尝试使用动态创建的表达式执行List.Find。简而言之,这就是:
list.Find(m => m.ListOfStrings.Exists(s => s == "cookie"));
其中m是
class MyClass
{
public List<string> ListOfStrings { get; set; }
}
我已经创造了
s => s == "cookie"
用表达式,没问题。我还为Exists宣布了一个methodinfo
var existsMethod = typeof(MyClass)
.GetProperty("ListOfStrings")
.PropertyType
.GetMethod("Exists");
我唯一的问题是创建一个表达式来调用lambda作为参数的所谓方法
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());
}
答案 0 :(得分:2)
代表们有不同的类型:
public delegate bool Predicate<T>(T obj);
public delegate TResult Func<T, TResult>(T arg);
Exists
方法(以及Find
)期望Predicate<T>
。 Lambda表达式在运行时编译为Func<T, TResult>
。
尝试以下方法:
var existsLambda = Expression.Lambda(typeof(Predicate<string>),
Expression.Equal(
Expression.Parameter(typeof(string), "s"),
Expression.Constant("cookie")),
Expression.Parameter(typeof(string), "s"));
您还可以使用通用Lambda Function:
var existsLambda = Expression.Lambda<Predicate<string>>(Expression.Equal(
Expression.Parameter(typeof(string), "s"),
Expression.Constant("cookie")),
Expression.Parameter(typeof(string), "s"));
答案 1 :(得分:0)
如果您查看该消息,它会告诉您Predicate与Func不兼容。
现在,Predicate被定义为:
public delegate bool Predicate<T>(
T obj
)
你有这样的Func:
public delegate TResult Func<T, Result>(
T arg1
)
放在一起,你试图使这两个代表兼容:
public delegate bool MyClassPredicate ( MyClass obj )
public delegate bool StringFunc ( string arg1 )
IE中。 string!= MyClass。
我希望这是有道理的。