Метод расширения с динамически созданным предикатом linq - PullRequest
1 голос
/ 21 октября 2010

У меня есть этот метод расширения.

        public static IQueryable<T> SearchBy<T>(this IQueryable<T> source, SearchCriteria criteria)
    {
        //throw an error if the source is null
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }

        ParameterExpression parameter = Expression.Parameter(source.ElementType, string.Empty);
        var property = Expression.Equal(Expression.PropertyOrField(parameter, criteria.Property), Expression.Constant(criteria.PropertyValue));
        LambdaExpression lambda = Expression.Lambda(property, parameter);

        Expression methodCallExpression = Expression.Call(typeof(Queryable), "SelectMany",
                                            new Type[] { source.ElementType, property.Type },
                                            source.Expression, Expression.Quote(lambda));

        return source.Provider.CreateQuery<T>(methodCallExpression);
    }

Я получаю эту ошибку

 No method 'SelectMany' on type 'System.Linq.Queryable' is compatible with the         supplied arguments.
    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: No method 'SelectMany' on type 'System.Linq.Queryable' is compatible with the supplied arguments.

Source Error:

Line 67:             LambdaExpression lambda = Expression.Lambda(property, parameter);
Line 68: 
Line 69:             Expression methodCallExpression = Expression.Call(typeof(Queryable), "SelectMany",
Line 70:                                                 new Type[] { source.ElementType, property.Type },
Line 71:                                                 source.Expression, Expression.Quote(lambda));

, когда я вызываю этот метод из структуры сущностей, как этот

this.grdReservations.DataSource = dataContext.CustomerSet.SearchBy(crit);

это критерии поиска

        SearchCriteria crit = new SearchCriteria();
        crit.Property = "UserName";
        crit.PropertyValue = "new_user";
        crit.Search = SearchType.Equal;

Если бы кто-нибудь мог взглянуть и дать мне толчок в правильном направлении, я был бы очень рад.

Спасибо за ваше время.

Редактировать: я дома, поэтому не могу проверить, но все методы, которые я пробую («Выбрать», «Где», «Выбрать»), все вернули эту ошибку, поэтому я предполагаю, что яделать что-то еще неправильно.

Ответы [ 3 ]

1 голос
/ 21 октября 2010
 this works

public static IQueryable<T> SearchBy<T>(this IQueryable<T> source, SearchCriteria criteria)
    {
        //throw an error if the source is null
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }

        ParameterExpression parameter = Expression.Parameter(source.ElementType, string.Empty);
        BinaryExpression property = Expression.Equal(Expression.PropertyOrField(parameter, criteria.Property), Expression.Constant(criteria.PropertyValue));
        LambdaExpression lambda = Expression.Lambda(property, parameter);

        Expression methodCallExpression = Expression.Call(typeof(Queryable), "Where",
                                            new Type[] { source.ElementType },
                                            source.Expression, Expression.Quote(lambda));

        return source.Provider.CreateQuery<T>(methodCallExpression);
    }

Мне нужно было изменить массив типов Expression.Call на этот

new Type[] { source.ElementType }

Этот пример очень помог.

Спасибо за ваше время, ребята

1 голос
/ 21 октября 2010

Вы хотите вызвать SelectMany или просто Select?

SelectMany ожидает, что лямбда возвращает IEnumerable [TResult], а не TResult.

0 голосов
/ 21 октября 2010

Похоже, что лямбда принимает значение параметра типа T и возвращает значение bool.Похоже, что он должен возвращать IEnumerable вместо этого.

Или, если вы измените «SelectMany» на «Select», лямбда-код должен будет вернуть значение типа T.

...