Frage

Wenn ein Expression<T> kompiliert wird, ist der resultierende Code implizit vom Framework zwischengespeichert? Ich bin nach dem Vorbild der statischen Regex Methoden denken, wo der Rahmen implizit erstellt und speichert die letzten paar reguläre Ausdrücke.

Wenn kompiliert Expression<T> Objekte sind nicht im Cache gespeichert, können Sie einige Best Practices empfehlen die Compile-Zeit oder Fallstricke zu halten, die Probleme verursachen könnte, wenn ich manuell einen Ausdruck cachen?

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

In diesem Beispiel bin ich etwas besorgt, dass, wenn ich den kompilierten Ausdruck zwischenzuspeichern, dass sie die Werte von arg1 und arg2 verwenden werden, da sie zu dem Zeitpunkt waren der Ausdruck kompiliert wurde, anstatt diese Werte von der entsprechenden Stelle Abrufen in dem Stapel (dh anstatt sich die aktuellen Werte).

War es hilfreich?

Lösung

Nein; Ich glaube nicht, dass es ist; wenn Sie es zwischengespeichert möchten, können Sie auf die Delegate Referenz halten muss (in der Regel Func<...> oder Action<...>). Ebenso, wenn Sie die beste Leistung erhalten möchten, würden Sie es als eine parametrierbare Ausdruck zusammenstellen, so können Sie in verschiedenen Werten senden, wenn Sie es aufrufen.

In diesem Fall wieder Formulierung würde helfen:

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

d. machen die Zahlen Parameter des Ausdrucks, und übergeben Sie die eigentlichen diejenigen es zur Laufzeit (statt Konstanten im Ausdruck ist).

Andere Tipps

Lambda experssions werden nicht automatisch zwischengespeichert. Sie müssen Sie eigene Caching / memoization Algorithmen für das implementieren. Überprüfen Sie die zugehörige Frage Stackoverflow:

Ist es möglich, einen Wert in einem Lambda-Ausdruck ausgewertet zwischenzuspeichern?

Es ist wichtig, dass die Lambda-Ausdrücke faul in C # ausgewertet ist zu notieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top