-2

我遇到了一些挑战,我必须创建一个表达式树来表示用户的查询输入。由于我没有时间创建所有可能的用户输入案例,我认为表达式树可以帮助我解决这个问题。

在大多数情况下,它有。然而,我有点难过。我在下面的代码中尝试使用动态创建的表达式执行 List.Find。简而言之,表达式是这样的:

list.Find(m => m.ListOfStrings.Exists(s => s == "cookie"));

其中 m 是

class MyClass
{
    public List<string> ListOfStrings { get; set; }
}

我已经做到了创造

s => s == "cookie"

有表情,没问题。我还为 Exists 声明了一个方法信息

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

2 回答 2

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 函数

var existsLambda = Expression.Lambda<Predicate<string>>(Expression.Equal(
                    Expression.Parameter(typeof(string), "s"),
                    Expression.Constant("cookie")),
                Expression.Parameter(typeof(string), "s"));
于 2009-05-25T16:26:12.747 回答
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。字符串!= MyClass。

我希望这是有道理的。

于 2009-05-25T16:19:44.743 回答