Existe uma razão específica para que o expansor do LinqKit não consiga captar expressões dos campo

Estou a usar LinqKit biblioteca que permite combinar expressões em tempo rea

Esta é uma alegria pura para escrever a camada de acesso a dados do Entity Framewok, porque várias expressões podem opcionalmente ser reutilizadas e combinadas, o que permite um código legível e eficient

Considere o seguinte trecho de código:

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

Declaramos uma expressão que projetaMessage paraMessageView (Removi os detalhes para maior clareza

Agora, o código de acesso a dados pode usar esta expressão para obter mensagens individuais:

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

Isso é lindo porque a mesma expressão pode ser reutilizada para obter uma lista de mensagens:

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

Como você pode ver, a expressão de projeção é armazenada em_selectMessageViewExpr e é usado para criar várias consultas diferente

No entanto, passei muito tempo rastreando um erro estranho ondeeste código falhou emExpand() liga.
O erro disse:

Não foi possível converter o objeto do tipoSystem.Linq.Expressions.FieldExpression digitarSystem.Linq.Expressions.LambdaExpression.

Só depois de um tempo eu percebi quetudo funciona quando a expressão é referenciada em uma variável local antes de ser chamadaInvoke e:

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

Est código @ funciona como esperad

Minha pergunta é

Existe algum motivo específico para o LinqKit não reconhecerInvoke em expressões armazenadas em campos? É apenas uma omissão do desenvolvedor, ou há algum motivo importante pelo qual as expressões precisam ser armazenadas nas variáveis locais primeir

Esta pergunta provavelmente pode ser respondida consultando o código gerado e verificando as fontes do LinqKit, no entanto, pensei que talvez alguém relacionado ao desenvolvimento do LinqKit pudesse responder a essa pergunt

Obrigado

questionAnswers(2)

yourAnswerToTheQuestion