代码之家  ›  专栏  ›  技术社区  ›  J. Steen

表达式与谓词问题

  •  -2
  • J. Steen  · 技术社区  · 15 年前

    在很大程度上,它已经做到了。然而,我有点不知所措。我在下面的代码中尝试使用动态创建的表达式执行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());
    }
    
    2 回复  |  直到 15 年前
        1
  •  2
  •   J. Steen    10 年前

    学员有不同的类型:

    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"));
    
        2
  •  0
  •   kastermester    15 年前

    如果查看消息,它会告诉您谓词与Func不兼容。

    现在,谓词的定义如下:

    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 )
    

    例如,字符串!=我的班级。

    我希望这是有道理的。