2010-03-24 3 views
4

UpdateСоздание запроса LINQ с помощью деревьев выражений

Благодаря помощи Марка, класс AlphaPagedList is now available on CodePlex если кто-то заинтересован

Оригинал

Я пытаюсь создать дерево выражения для возвращаемые элементы, начинающиеся с заданного charecter.

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

Нечто подобное (EDITED после повторного чтения вопроса) - но обратите внимание, что Expression.Invoke не работает на EF в 3.5SP1 (но это хорошо в 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

Смежные вопросы