7

Is possible to convert a Predicate<T> to Expression<Func<T, bool>> in some way?

I would like to use the next IQueryable function using the filters of the my ICollectionView:

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

Thanks

  • 2
    Difficult to do in a reasonable way(i.e. not by just wrapping it). That would involve decompiling IL to an expression. – CodesInChaos Mar 21 '12 at 10:04
  • No. Predicate is a compiled delegate. You could do such a thing, but with a Expression>. – Olivier Mar 21 '12 at 10:05
  • @MarcCanalsGiraut: It seems like a bad idea... Why would you want to do this? Can't you change any of the existing code to avoid the problem in the first place? – Mark Byers Mar 21 '12 at 10:20
  • Don't forget to mark your favorite answer ;-) – Steven Apr 17 '13 at 16:00

3 Answers3

6

Something like this?

Predicate<string> predicate = input => input.Length > 0;
Expression<Func<string, bool>> expression = (input) => predicate(input);

You can probably make an extension Where method for your ICollectionView which takes a predicate, converts it to an Expression like this, and then call the Where method provided by Linq.

public static IQueryable<T> Where(this IQueryable<T> source, Predicate<T> predicate)
{
    return source.Where(x => predicate(x));
}
Jesse van Assen
  • 2,240
  • 2
  • 16
  • 19
  • 4
    -1: This wouldn't work in every case where the expression is not executed but analyzed like in LINQ to SQL, LINQ to EF, LINQ to NHibernate etc... – Daniel Hilgarth Mar 21 '12 at 10:12
  • Yes, I am aware. However, the asker mentioned that he needs it for his implementation of ICollectionView, which is used in WPF for GUI rendering, as seen [here](http://msdn.microsoft.com/en-us/library/system.componentmodel.icollectionview.aspx) at the 'Remarks' section. – Jesse van Assen Mar 21 '12 at 10:19
  • 1
    It's the other way around :-) He wants to use the filters created for his `ICollectionView` in a `Where` clause. – Daniel Hilgarth Mar 21 '12 at 10:22
  • Just out of curiosity, what happens when you do `new Func(predicate)`? Is it converted to the Func so it can be analyzed, or does it get called and give the same result as explicitly calling the predicate? – Jesse van Assen Mar 21 '12 at 10:32
  • 1
    I don't know what happens when you do this, but it doesn't help you, because a `Func` isn't an `Expression>` and can't be converted to one. – Daniel Hilgarth Mar 21 '12 at 10:36
  • 1
    I thought the Func was analysed when the Expression is called, but now I see I perceived it wrong. The Func is just there to strong type the Expression, but not actually perform the analysis on. Thank you for your explanation. – Jesse van Assen Mar 21 '12 at 10:40
5

In theory it is possible to convert a delegate 'back' to an expression, because you can request the emitted IL of a delegate, which gives you the information you need to transform it back.

However, it's for a reason that neither LINQ to SQL and Entity Framework do this. It is complex, fragile, and performance intensive to do so.

So the short answer is, you can't transform it to an expression.

Steven
  • 166,672
  • 24
  • 332
  • 435
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 });
        }
    }
}