【问题标题】:Generating a LINQ query using Expression Trees使用表达式树生成 LINQ 查询
【发布时间】:2010-03-24 17:16:37
【问题描述】:

更新

感谢 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=&gt;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));
}

【问题讨论】:

    标签: c# linq lambda expression-trees


    【解决方案1】:

    类似(EDITED 重新阅读问题后) - 但请注意 Expression.Invoke 不适用于 3.5SP1 中的 EF(但在 LINQ-to-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);
        }
    }
    

    【讨论】:

    • 完美,非常感谢。我正在处理一个字母数字分页列表(沿 IPagedList 行),这将是无价的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 2014-10-16
    • 2020-08-20
    • 1970-01-01
    相关资源
    最近更新 更多