2010-03-24 110 views
4

更新使用表达式树

多亏了马克的帮助下AlphaPagedList类is now available on CodePlex如果有人有兴趣生成LINQ查询

原始

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

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)); 
} 

回答

2

喜欢的东西(重新阅读的问题后可进行编辑) - 但请注意,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); 
    } 
} 
+0

非常完美,非常感谢。我正在处理一个字母数字分页列表(沿着IPagedList的方向),这是非常宝贵的。 – Chao 2010-03-25 09:52:48