Obtenir Func <T> et Expression <Func <T >> à partir d'un seul paramètre?

Je voudrais obtenir à la fois le Func compilé (de booléen) et un Expression (de Func (de booléen)) en utilisant un seul paramètre. Je n'ai pas l'intention de modifier l'arbre d'expression. La seule raison de prendre un arbre d'expression du tout est donc je peux imprimer le code qui est en cours d'exécution.

void Assert(Expression> assertionExpression) {
    if (!assertionExpression.Compile()()) 
    { 
        throw new AssertFailedException(assertionExpression.ToString()); 
    }
}

Y a-t-il un moyen raisonnable de le faire?

En tant que corrolaire, dans le cas d'arbres d'expression simples générés par un compilateur, la même instance sera-t-elle toujours passée en paramètre?

static Dictionary>, Func> cache;

static void Assert(Expression> assertionExpression) {
    Func method = null;
    if (!cache.TryGetValue(assertionExpression, out method)) {
        cache.Add(assertionExpression, method = assertionExpression.Compile());
        Console.WriteLine("cache insert");
    }
    else {
         Console.WriteLine("cache hit");
    }
    if (!method()) 
    { 
        throw new AssertFailedException(assertionExpression.ToString()); 
    }
}

static void someCodeThatExecutesRegularly() {
    Assert(()=>true);
}

public static void Main(string[] args, int argc) 
{
    someCodeThatExecutesRegularly();

    someCodeThatExecutesRegularly();

    someCodeThatExecutesRegularly();
}

La sortie sera-t-elle 'insert de cache,' cache hit ',' cache hit 'ou' cache insert ',' cache insert ',' cache insert '.

0

1 Réponses

Pour la première question, vous pouvez prendre l'arbre d'expression et le compiler pour obtenir une version exécutable, bien qu'il soit recompilé à chaque fois, vous devrez donc le mettre en cache.

static void Assert(Expression> assertionExpression) {
    var func = assertionExpression.Compile();//if you call func() it will execute the expression
}

Pour votre deuxième question, il s'agira à chaque fois d'un nouvel arbre d'expression, donc vous obtiendrez "cache insert" "cache insert" "cache insert" etc ...

Pour l'utiliser avec le cache et la compilation, vous pouvez éventuellement utiliser .ToString() sur l'expression pour obtenir la représentation sous forme de chaîne de la fonction, mais cela peut causer des problèmes de confusion si vous avez des fermetures les variables fermées seraient différentes, donc si vous faites cela, USE WITH CARE!

0
ajouté