如何为IQueryable应用表达式树
本文关键字:表达式 应用 IQueryable | 更新日期: 2023-09-27 17:54:00
是否有任何方法将手动创建的表达式树从一个IQueryable应用到另一个IQueryable ?例如:
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);
或者我们必须分别应用Where
和OrderBy
表达式?
简单的CreateQuery
调用不工作,因为提供者使用传入表达式的数据源。
在执行表达式之前,您需要用您的数据集合替换Enumerable.Empty<string>()
:
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);
}
}
}
您可以访问查询的提供程序并使用CreateQuery
创建基于表达式的查询,并且您可以从另一个查询中获取要传递给它的表达式:
var filteredResult = vv.Provider.CreateQuery<string>(p.Expression);
我有一个类似的情况,我必须通过WCF发送筛选/排序表达式。我找不到同时使用过滤器和排序表达式的单个实例的方法。我最终使用了InterLinq的SerializableExpression。虽然不能解决你的问题,但我希望它能有所帮助。