Pregunta

Cuando se compila una Expression < T > , ¿el marco resultante almacena en caché implícitamente el código resultante? Estoy pensando en la línea de los métodos estáticos Regex donde el marco compila y almacena en caché implícitamente las últimas expresiones regulares.

Si los objetos compilados Expression < T > no se almacenan en caché, ¿puede recomendar algunas prácticas recomendadas para mantener el tiempo de compilación inactivo o cualquier problema que pueda causar problemas si yo guardar en caché manualmente una expresión?

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

En este ejemplo, me preocupa un poco que si guardo en caché la expresión compilada, usará los valores de arg1 y arg2 como estaban en ese momento la expresión se compiló, en lugar de recuperar esos valores del lugar apropiado en la pila (es decir, en lugar de obtener los valores actuales).

¿Fue útil?

Solución

No; No creo que sea así; si desea almacenarlo en caché, debe conservar la referencia Delegate (normalmente Func < ... > o Action < ... > ). Del mismo modo, si desea obtener el mejor rendimiento, lo compilará como una expresión parametrizada, para que pueda enviar diferentes valores cuando lo invoque.

En este caso, la reformulación ayudaría:

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

es decir haga los parámetros numéricos de la expresión y pase los reales en tiempo de ejecución (en lugar de ser constantes en la expresión).

Otros consejos

Las expresiones Lambda no se almacenan en caché automáticamente. Deberá implementar sus propios algoritmos de almacenamiento en caché / memoria para eso. Consulte la pregunta relacionada con Stackoverflow:

es ¿Es posible almacenar en caché un valor evaluado en una expresión lambda?

Es importante tener en cuenta que las expresiones lambda son vagas evaluadas en C #.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top