将 Predicate<T> 转换为 Expression<Func<T, bool>>

7

有没有可能以某种方式将 Predicate<T> 转换为 Expression<Func<T, bool>>

我想使用下一个 IQueryable 函数来使用我的 ICollectionView 的过滤器:

public static System.Linq.IQueryable<TSource> Where<TSource>(this System.Linq.IQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, bool>> predicate)

谢谢


2
以合理的方式实现这个可能有些困难(即不能只是简单地包装它)。这将涉及将IL反编译为表达式。 - CodesInChaos
No. Predicate<T> 是一个已编译的委托。你可以这样做,但需要使用 Expression<Predicate<T>>。 - Olivier
@MarcCanalsGiraut:这似乎是个不好的想法... 为什么你要这样做呢?难道你不能修改现有的代码以避免出现问题吗? - Mark Byers
不要忘记标记你最喜欢的答案;-) - Steven
3个回答

6
像这样的吗?
Predicate<string> predicate = input => input.Length > 0;
Expression<Func<string, bool>> expression = (input) => predicate(input);

你可以为你的 ICollectionView 创建一个扩展方法 Where,该方法接受一个谓词并将其转换为如下所示的表达式,然后调用 Linq 提供的 Where 方法。
public static IQueryable<T> Where(this IQueryable<T> source, Predicate<T> predicate)
{
    return source.Where(x => predicate(x));
}

5
这并不适用于每个情况,比如在LINQ to SQL、LINQ to EF、LINQ to NHibernate等需要分析表达式而非执行表达式的情况下。 - Daniel Hilgarth
是的,我知道。然而,提问者提到他需要它来实现ICollectionView,这在WPF中用于GUI渲染,如此处所示,在“备注”部分。 - Jesse van Assen
1
这正好相反 :-) 他想在 Where 子句中使用为他的 ICollectionView 创建的过滤器。 - Daniel Hilgarth
只是出于好奇,当你执行 new Func<string, bool>(predicate) 时会发生什么?它会被转换为 Func 以便进行分析,还是会被调用并给出与显式调用谓词相同的结果? - Jesse van Assen
1
我不知道你这样做会发生什么,但它对你没有帮助,因为Func<string, bool>不是Expression<Func<string, bool>>,也不能被转换为一个。 - Daniel Hilgarth
1
我曾以为当调用表达式时,Func 会被分析,但现在我意识到我错了。Func 只是用来强制类型化表达式,而不是实际执行分析的。感谢您的解释。 - Jesse van Assen

5
在理论上,将委托“转换”回表达式是可能的,因为您可以请求委托的发出的IL代码,这会提供您需要将其转换回去的信息。
然而,这正是LINQ to SQL和Entity Framework不这样做的原因。这样做很复杂、易碎且性能密集。
所以简短的答案是,您无法将其转换为表达式。

1
namespace ConsoleApplication1
{
    static class Extensions
    {
        public static Expression<Func<T, bool>> ToExpression<T>(this Predicate<T> p)
        {
            ParameterExpression p0 = Expression.Parameter(typeof(T));
            return Expression.Lambda<Func<T, bool>>(Expression.Call(p.Method, p0), 
                  new ParameterExpression[] { p0 });
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接