代码之家  ›  专栏  ›  技术社区  ›  Jon Smock

使用C中的反射将func转换为谓词#

  •  5
  • Jon Smock  · 技术社区  · 14 年前

    我基本上是在尝试 this 但是我不知道会是什么,所以我用反射树和表达树来构建事物。

    // Input (I don't know about "Book")
    Type itemType = typeof(Book);
    
    // Actual Code
    // Build up func p => p.AuthorName == "Jon Skeet"
    ParameterExpression predParam = Expression.Parameter(itemType, "p");
    Expression left = Expression.Field(predParam, itemType.GetField("AuthorName"));
    Expression right = Expression.Constant("Jon Skeet", typeof(string));
    Expression equality = Expression.Equal(left, right);
    Delegate myDelegate = Expression.Lambda(equality, new ParameterExpression[] { predParam }).Compile(); // Not sure if I need this
    
    // Build up predicate type (Predicate<Book>)
    Type genericPredicateType = typeof(Predicate<>);
    Type constructedPredicateType = genericPredicateType.MakeGenericType(new Type[] { itemType });
    
    // I need an instance to use this predicate, right? (** This Fails **)
    object predicateInstance = Activator.CreateInstance(constructedPredicateType, new object[] { myDelegate });
    

    基本上,我有一个 List<Book> ,我正试图思考的是, Invoke 它的 Find 方法。这个 发现 方法需要 Predicate<Book> 而不是 Func<Book, bool> 我在这上面打了几个小时。

    编辑:以下是错误跟踪的第一部分:

    System.MissingMethodException: Constructor on type 'System.Predicate`1[[MyProject.Book, MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' not found.
    
    2 回复  |  直到 14 年前
        1
  •  3
  •   Jon Skeet    14 年前

    幸运的是,只需将您的呼叫更改为 Expression.Lambda :

    Type predicateType = typeof(Predicate<>).MakeGenericType(itemType);
    LambdaExpression lambda = Expression.Lambda(predicateType, equality, predParam);
    Delegate compiled = lambda.Compile();
    

    现在还不清楚你需要对结果做些什么,注意……如果弱类型版本适合您,那就没问题了。

        2
  •  0
  •   Daniel Renshaw    14 年前

    不确定这是否与乔恩的答案相同:

    public static Predicate<T> GetPredicate<T>()
    {
        Type itemType = typeof(T);
        ParameterExpression predParam = Expression.Parameter(itemType, "p");
        Expression left = Expression.Field(predParam, itemType.GetField("AuthorName"));
        Expression right = Expression.Constant("Jon Skeet", typeof(string));
        Expression equality = Expression.Equal(left, right);
        Func<T, bool> function = (Func<T, bool>)Expression.Lambda(equality, new[] { predParam }).Compile();
        return new Predicate<T>(function);
    }