c# - 使用表达式树生成 LINQ 查询

标签 c# linq lambda expression-trees

更新

感谢 Marc 帮助 AlphaPagedList 类 is now available on CodePlex如果有人感兴趣

原创

我正在尝试创建一个表达式树以返回以给定字符开头的元素。

IList<char> chars = new List<char>{'a','b'};
IQueryable<Dept>Depts.Where(x=> chars.Contains(x.DeptName[0]));

我希望在任何 IEnumerable 上使用它,我在其中为属性提供了一个 lamdba 以供选择,例如:

Depts.Alpha(x=>x.DeptName, chars);

我一直在尝试这个,但一点运气都没有,有什么帮助吗?

public static IQueryable<T> testing<T>(this IQueryable<T> queryableData, Expression<Func<T,string>> pi, IEnumerable<char> chars)
{
// Compose the expression tree that represents the parameter to the predicate.

ParameterExpression pe = Expression.Parameter(queryableData.ElementType, "x");
ConstantExpression ch = Expression.Constant(chars,typeof(IEnumerable<char>));
// ***** Where(x=>chars.Contains(x.pi[0])) *****
// pi is a string property
//Get the string property

Expression first = Expression.Constant(0);
//Get the first character of the string
Expression firstchar = Expression.ArrayIndex(pi.Body, first);
//Call "Contains" on chars with argument being right
Expression e = Expression.Call(ch, typeof(IEnumerable<char>).GetMethod("Contains", new Type[] { typeof(char) }),firstchar);


MethodCallExpression whereCallExpression = Expression.Call(
    typeof(Queryable),
    "Where",
    new Type[] { queryableData.ElementType },
    queryableData.Expression,
    Expression.Lambda<Func<T, bool>>(e, new ParameterExpression[] { pe }));
// ***** End Where *****

return (queryableData.Provider.CreateQuery<T>(whereCallExpression));
}

最佳答案

类似于(EDITED 在重新阅读问题后) - 但请注意 Expression.Invoke 在 3.5SP1 的 EF 上不起作用(但在LINQ 到 SQL):

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

class Dept
{
    public string DeptName { get; set; }
}
public static class Program
{
    static void Main()
    {
        IList<char> chars = new List<char>{'a','b'};
        Dept[] depts = new[] { new Dept { DeptName = "alpha" }, new Dept { DeptName = "beta" }, new Dept { DeptName = "omega" } };
        var count = testing(depts.AsQueryable(), dept => dept.DeptName, chars).Count();
    }

    public static IQueryable<T> testing<T>(this IQueryable<T> queryableData, Expression<Func<T,string>> pi, IEnumerable<char> chars)
    {
        var arg = Expression.Parameter(typeof(T), "x");
        var prop = Expression.Invoke(pi, arg);
        Expression body = null;
        foreach(char c in chars) {
            Expression thisFilter = Expression.Call(prop, "StartsWith", null, Expression.Constant(c.ToString()));
            body = body == null ? thisFilter : Expression.OrElse(body, thisFilter);
        }
        var lambda = Expression.Lambda<Func<T, bool>>(body ?? Expression.Constant(false), arg);
        return queryableData.Where(lambda);
    }
}

关于c# - 使用表达式树生成 LINQ 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2509855/

相关文章:

Java 8 组合,柯里化(Currying)简写

c# - C#(或C++)与JAVA之间如何通信

c# - 为什么 Configuration.FilePath 返回不存在的文件?

c# - 如何在不使用基本查询的情况下在一项操作中解析多个 linq 查询?

c# - 与 LINQ 中的集合集合相交

linq - 如何在 Mono 中使用 LINQ?

C# 关于将文本写入文件的最佳方式的建议,如果在记事本中打开,用户将无法理解它

c# - 如何使用简单注入(inject)器模拟模块/安装程序/注册表

c# - 为什么 C# 不能使用内联匿名 lambda 或委托(delegate)?

c# - Lambda 表达式作为字典中的键