только когда мне это действительно нужно.

ользуюLinqKit библиотека, которая позволяет комбинировать выражения на лету.

Это чистое блаженство для написания слоя доступа к данным Entity Framewok, потому что несколько выражений можно при желании использовать повторно и комбинировать, что позволяет и для удобочитаемого, и для эффективного кода.

Рассмотрим следующий фрагмент кода:

private static readonly Expression<Func<Message, int, MessageView>> _selectMessageViewExpr =
    ( Message msg, int requestingUserId ) =>
        new MessageView
        {
            MessageID = msg.ID,
            RequestingUserID = requestingUserId,
            Body = ( msg.RootMessage == null ) ? msg.Body : msg.RootMessage.Body,
            Title = ( ( msg.RootMessage == null ) ? msg.Title : msg.RootMessage.Title ) ?? string.Empty
        };

Мы объявляем выражение, что проектыMessage наMessageView (Я удалил детали для ясности).

Теперь код доступа к данным может использовать это выражение для получения отдельного сообщения:

var query = CompiledQueryCache.Instance.GetCompiledQuery(
    "GetMessageView",
    () => CompiledQuery.Compile(
        _getMessagesExpr
            .Select( msg => _selectMessageViewExpr.Invoke( msg, userId ) ) // re-use the expression
            .FirstOrDefault( ( MessageView mv, int id ) => mv.MessageID == id )
            .Expand()
        )
    );

Это прекрасно, потому что одно и то же выражение можно использовать и для получения списка сообщений:

var query = CompiledQueryCache.Instance.GetCompiledQuery(
    "GetMessageViewList",
    () => CompiledQuery.Compile(
        BuildFolderExpr( folder )
            .Select( msg => _selectMessageViewExpr.Invoke( msg, userId ) )
            .OrderBy( mv => mv.DateCreated, SortDirection.Descending )
            .Paging()
            .Expand()
        ),
    folder
    );

Как видите, выражение проекции хранится в_selectMessageViewExpr и используется для построения нескольких разных запросов.

Тем не менее, я потратил много времени на поиск странной ошибки, когдаэтот код разбился приExpand() вызов.
Ошибка сказала:

Невозможно привести объект типаSystem.Linq.Expressions.FieldExpression печататьSystem.Linq.Expressions.LambdaExpression.

Только через некоторое время я понял, чтовсе работает, когда выражение вызывается в локальной переменной перед вызовомInvoke на:

var selector = _selectMessageViewExpr; // reference the field

var query = CompiledQueryCache.Instance.GetCompiledQuery(
    "GetMessageView",
    () => CompiledQuery.Compile(
        _getMessagesExpr
            .Select( msg => selector.Invoke( msg, userId ) ) // use the variable
            .FirstOrDefault( ( MessageView mv, int id ) => mv.MessageID == id )
            .Expand()
        )
    );

Этот код работает как положено.

Мой вопрос:

Есть ли конкретная причина, почему LinqKit не распознаетInvoke на выражения, хранящиеся в полях? Является ли это просто упущением разработчика или есть какая-то важная причина, по которой выражения должны сначала храниться в локальных переменных?

Ответ на этот вопрос, вероятно, можно получить, взглянув на сгенерированный код и проверив источники LinqKit, однако я подумал, что, возможно, кто-то, имеющий отношение к разработке LinqKit, мог бы ответить на этот вопрос.

Благодарю.

Ответы на вопрос(2)

Ваш ответ на вопрос