Reputation: 3043
Update
Thanks to Marc's help the AlphaPagedList class is now available on CodePlex if anyone is interested
Original
I'm trying to create an expression tree to return elements that start with a given charecter.
IList<char> chars = new List<char>{'a','b'};
IQueryable<Dept>Depts.Where(x=> chars.Contains(x.DeptName[0]));
I want this to be used on any IEnumerable where I provide a lamdba to the property to select on eg:
Depts.Alpha(x=>x.DeptName, chars);
I've been trying this but having no luck at all, any help?
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));
}
Upvotes: 4
Views: 3206
Reputation: 1062502
Something like (EDITED after re-reading the question) - but note that Expression.Invoke
doesn't work on EF in 3.5SP1 (but it is fine in 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);
}
}
Upvotes: 2