How to apply an expression tree for IQueryable?

c# entity-framework expression-trees iqueryable linq-to-sql

Question

Is there any way to apply a manually created expression tree from one IQueryable to another? For example:

IQueryable<string> p = Enumerable.Empty<string>().AsQueryable();
p = p.Where(pp => pp[0] == 'A');
p = p.Skip(2).Take(4);
p = p.OrderBy(pp => pp.Length);

var vv = new[] {"Afss", "Acv", "Adfv", "Bcvx", "Ng"}.AsQueryable();

// Filtering of the vv collection with expression from p 
var filteredResult = vv.Filter(p.Expression);

Or we have to separately apply the Where and OrderBy expressions?

Popular Answer

Simple CreateQuery call does not work, because provider uses data source of the passed expression.

Before executing expression you need to replace Enumerable.Empty<string>() by a collection with your data:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

public class Program
{
    public static void Main()
    {
        IQueryable<string> p = Enumerable.Empty<string>().AsQueryable();
        p = p.Where(pp => pp[0] == 'A');
        p = p.Skip(2).Take(4);
        p = p.OrderBy(pp => pp.Length);

        var vv = new[] {"Afss", "Acv", "Adfv", "Bcvx", "Ng"}.AsQueryable();

        // Filtering of the vv collection with expression from p 
        var expr = ExpressionTreeConstantReplacer.CopyAndReplace(p.Expression, typeof(EnumerableQuery<string>), vv);
        var filteredResult = vv.Provider.CreateQuery<string>(expr);

        Console.Write("Source: \t");
        foreach(var temp in vv)
            Console.Write("{0} ", temp);

        Console.WriteLine();

        Console.Write("Filtered: ");
        foreach(var temp in filteredResult)
            Console.WriteLine(temp);
    }

    class ExpressionTreeConstantReplacer<T> : ExpressionVisitor
    {
        Type originalType;
        T replacementConstant;

        internal ExpressionTreeConstantReplacer(Type originalType, T replacementConstant)
        {
            this.originalType = originalType;
            this.replacementConstant = replacementConstant;
        }

        protected override Expression VisitConstant(ConstantExpression c)
        {
            return c.Type == originalType ? Expression.Constant(replacementConstant) : c;
        }
    }

    class ExpressionTreeConstantReplacer
    {
        internal static Expression CopyAndReplace<T>(Expression expression, Type originalType, T replacementConstant)
        {
            var modifier = new ExpressionTreeConstantReplacer<T>(originalType, replacementConstant);
            return modifier.Visit(expression);
        }
    }
}


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why