4

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

1 Answer 1

2

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);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Perfect, thanks so much for this. I'm working on an alpha-numeric paged list (along the lines of IPagedList) and this will be invaluable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.