Pergunta

Quando um Expression<T> é compilado, é o código resultante em cache implicitamente pela estrutura? Estou pensando ao longo das linhas dos métodos Regex estáticos, onde o quadro compila implícita e armazena em cache os últimos expressões regulares.

Se objetos Expression<T> compilado são não em cache, você pode recomendar algumas das melhores práticas para manter o tempo de compilação para baixo ou alguma dicas que podem causar problemas se eu armazenar em cache manualmente uma expressão?

public MyResultType DoSomething(int arg1, int arg2)
{
    var result = invokeHandler(
        (IDoSomethingHandler h) => h.DoSomething(arg1, arg2)
    );
    return result;
}

private TResult invokeHandler<T, TResult>(Expression<Func<T, TResult>> action)
    where T : class
{
    // Here, I might want to check to see if action is already cached.

    var compiledAction = action.Compile();
    var methodCallExpr = action as MethodCallExpression;

    // Here, I might want to store methodCallExpr in a cache somewhere.

    var handler = ServiceLocator.Current.GetInstance<T>();
    var result = compiledAction(handler);

    return result;
}

Neste exemplo, estou um pouco preocupado que se eu armazenar em cache a expressão compilado, que usará os valores de arg1 e arg2 como eram na época a expressão foi compilado, em vez de recuperar esses valores a partir do local apropriado na pilha (ou seja, em vez de receber os valores atuais).

Foi útil?

Solução

Não; Eu não acredito que ele é; se você quiser em cache, você deve segurar a referência Delegate (tipicamente Func<...> ou Action<...>). Da mesma forma, se você deseja obter o melhor desempenho, você compilá-lo como uma expressão parametrizado, para que possa enviar valores diferentes quando você invocá-lo.

Neste caso, re-fraseado ajudaria:

public MyResultType DoSomething(int arg1, int arg2)
{
    var result = invokeHandler(
        (IDoSomethingHandler h, int a1, int a2) => h.DoSomething(a1, a2),
        arg1, arg2);
    return result;
}

private TResult invokeHandler<T, TResult>(Expression<Func<T,int,int,TResult>> action,
    int arg1, int arg2)
    where T : class
{
    // Here, I might want to check to see if action is already cached.

    var compiledAction = action.Compile();
    var methodCallExpr = action as MethodCallExpression;

    // Here, I might want to store methodCallExpr in a cache somewhere.

    var handler = ServiceLocator.Current.GetInstance<T>();
    var result = compiledAction(handler, arg1, arg2);

    return result;
}

i. fazer os números de parâmetros da expressão, e passar os reais aqueles que em tempo de execução (em vez de ser constantes na expressão).

Outras dicas

experssions Lambda não são armazenados em cache automaticamente. Você precisará implementar você próprios algoritmos de cache / memoização para isso. Verifique a questão Stackoverflow relacionados:

é possível armazenar em cache um valor avaliado em uma expressão lambda?

É importante notar que as expressões lambda são preguiçosos avaliado em C #.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top