C# Extension для Queryable.Where
От: Alexandr Sulimov Украина www.ase.com.ua
Дата: 21.06.14 05:47
Оценка:
Пишу Extension для IQueryablelist (EntityFramework)

IQueryablelist= db.Users;//Users table
//Поиск  символа "a" в полях которые передаю, это FirstName or LastName
list.ApplyFilterPatern("a", x => x.FirstName, x => x.LastName,...);
//результат работы аналогичен коду
list.Where(x => x.FirstName.ToLower().Contains("a") || x.LastName.ToLower().Contains("a"))


Вот что получилось написать
https://dotnetfiddle.net/zrGPfb

Дальше я запутался с lambda и generics

public class User
    {
        public string FirstName
        {
            get;
            set;
        }

        public string LastName
        {
            get;
            set;
        }

        public string MiddleName
        {
            get;
            set;
        }
    }

    public class Program
    {
        public static void Main()
        {
            List<User> users = new List<User>();
            users.Add(new User { FirstName = "a", LastName = "b" } );
            users.Add(new User { FirstName = "b", LastName = "a" } );
            users.Add(new User { FirstName = "b", LastName = "b" } );
            
            IQueryable<User> l = users.AsQueryable<User>();
            var r = ApplyFilterPatern(l, "a", x => x.FirstName, x => x.LastName);
        }

        public static IQueryable<T> ApplyFilterPatern<T>(IQueryable<T> source, string searchString, params Expression<Func<T, object>>[] properties)
        {
            Expression result = null;
            foreach (var item in properties)
            {
                var lambda = item as LambdaExpression;
                MemberExpression memberExpression;
                if (lambda.Body is UnaryExpression)
                {
                    var unaryExpression = (UnaryExpression)lambda.Body;
                    memberExpression = (MemberExpression)unaryExpression.Operand;
                }
                else
                {
                    memberExpression = (MemberExpression)lambda.Body;
                }

                var expr = Expression.Call(memberExpression, "ToLower", null, null);
                expr = Expression.Call(expr, typeof (string).GetMethod("Contains", new[] { typeof (string)}), Expression.Constant(searchString));
                if (result == null)
                    result = expr;
                else
                    result = Expression.Or(result, expr);
            }

            var parameter = Expression.Parameter(typeof (T), "x");
            var r = Expression.Lambda<Func<T, bool>>(result, parameter);
            Type predType = typeof (Func<, >).MakeGenericType(typeof (T), typeof (bool));
            Type predType2 = typeof (Expression<>).MakeGenericType(predType);
            
            MethodInfo mWhere = typeof (Queryable).GetMethods().Single(
                method => method.Name == "Where" 
                && method.IsGenericMethodDefinition 
                && method.GetGenericArguments().Length == 1 
                && method.GetParameters().Length == 2 
                && method.GetParameters()[1].ParameterType.GetGenericArguments().Length == 1 
                && method.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments().Length == 2);
            
            mWhere = mWhere.MakeGenericMethod(predType2);
            mWhere.Invoke(null, new object[] { source, r } );
            
            return source;
        }
    }


Run-time exception (line 82): Object of type 'System.Linq.EnumerableQuery`1[ASE.User]' cannot be converted to type 'System.Linq.IQueryable`1[System.Linq.Expressions.Expression`1[System.Func`2[ASE.User,System.Boolean]]]'.
Смелости хватает только под ником писать?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.