Generating a LINQ query using Expression Trees
Update
T开发者_JAVA百科hanks 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));
}
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);
}
}
精彩评论