Как работает вложение OrderBy в запрос Dynamic Linq?

Я использую Dynamic Linq, и сегодня я хотел создать немного более сложный вложенный запрос:

"Composition
.Where(((ExpirationDate > DateTime.UtcNow.Date) && (ExpirationDate.Year != 9999)))
.OrderBy(\"ExpirationDate ASC\")
.Select(ExpirationDate)
.FirstOrDefault() == @0"

(разрывы сделаны только для удобства чтения в этом посте, а не в коде)

Запрос хранится в строковой переменной и передается этому:

private static Func<IQueryable<T>, object, IQueryable<T>> CreateWhereExpression<T>(string whereClause) where T : class
{
     return (q, o) => q.Where(whereClause, o);
}

Что с радостью создает выражение Where. (обратите внимание, что whereClause содержит точную строку выше "Composition.Where....") Но как только наступит время выполнения, он будет жаловаться:

Подходящего статистического метода OrderBy не существует.

Итак, мой вопрос, что я делаю неправильно? Как я могу заставить работать вложенный OrderBy?


person Vincent    schedule 26.09.2014    source источник
comment
Вы пытаетесь разобрать LINQ? Dynamic LINQ не поддерживает анализ собственного синтаксиса.   -  person    schedule 26.09.2014
comment
Да, я пытаюсь заставить Dynamic Linq анализировать строку как запрос Linq. Я также попробовал это с синтаксисом Linq «.OrderBy (ExpirationDate)», но получил ту же ошибку. Я пытаюсь сделать что-то похожее на это: stackoverflow.com/questions/10314708/ Но с запросом по порядку.   -  person Vincent    schedule 26.09.2014


Ответы (1)


По умолчанию DynamicLinq поддерживает несколько функций для вложенных запросов к IEnumerable полям, все они определены в интерфейсе IEnumerableSignatures, например Where, Any, Count и т. д., но не имеют Orderby, Select или FirstOrDefault того, что вам нужно.
Таким образом, вы можете добавить это к этому интерфейсу, как

interface IEnumerableSignatures
{
    ....
    void OrderBy(object selector);
    void Select(object selector);
    void FirstOrDefault();
}

после этого вам нужно исправить ParseAggregate метод, подобный этому

Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos)
{
    ....
    if (signature.Name == "Min" || signature.Name == "Max" 
        || signature.Name == "OrderBy" || signature.Name == "Select" //add this for support OrderBy and Select that need two generic parameters
    )
    ....
}

наконец, следующий запрос будет работать

"Composition
.Where((ExpirationDate > DateTime.UtcNow.Date) && (ExpirationDate.Year != 9999))
.OrderBy(ExpirationDate)
.Select(ExpirationDate)
.FirstOrDefault() == @0"
person Grundy    schedule 27.09.2014
comment
+1. версия DynamicLinq, которую я использовал, исчезла из Nuget, и мне пришлось использовать базовую версию, в которой, по-видимому, отсутствует эта функциональность. Спасибо! - person John; 04.11.2016