9
votes

Cache Compilez de l'expression >

J'ai une classe que j'utilise pour les arguments de la méthode de contrôle, que vous appelez dans le formulaire: xxx pré>

si l'argument est null, alors un argumentnullexception code> avec Le nom de la propriété est lancé. Ceci est fait comme si: p> xxx pré>

getMemberName code> est une méthode d'extension que j'ai écrite. P>

Le problème que je ' m ayant que l'appel à compiler est très lent, je voudrais donc cacher le résultat, mais je ne semble pas pouvoir proposer une clé de cache qui sera suffisamment unique pour empêcher les conflits de cache, mais pas Si unique que le cache devienne invalide. P>

Mes meilleurs efforts jusqu'à présent sont les suivants: P>

internal static class ExpressionCache<T>
{
    private static readonly Dictionary<string, Func<T>> Cache = new Dictionary<string, Func<T>>();

    public static Func<T> CachedCompile(Expression<Func<T>> targetSelector)
    {
        Func<T> cachedFunc;
        var cacheKey = targetSelector + targetSelector.Body.ToString();

        if (!Cache.TryGetValue(cacheKey, out cachedFunc))
        {
            cachedFunc = targetSelector.Compile();
            Cache[cacheKey] = cachedFunc;
        }

        return cachedFunc;
    }
}


4 commentaires

J'utiliserais postshars ou il: abdullin.com/journal/2008/12/19/...


@Ruben, vous avez raison, j'ai piraté un peu un peu dans le navigateur avant de la publier. Je vais le corriger.


Puis-je vous demander pourquoi il doit être expression que vous avez mis à l'argument Checker ... pourquoi pas seulement la valeur? Est seulement pour pouvoir alors jeter cette exception?


Pourriez-vous fournir un échantillon de deux expressions qui seront en conflit?


3 Réponses :


0
votes

Jeffery zhao a quelques excellents messages sur ce sujet, malheureusement, ils sont écrits en chinois. Une bonne nouvelle est que vous pouvez télécharger le code de mise en œuvre complet de Expresshee Caching ici . Et personnellement, j'ai une autre suggestion: pourquoi pas contrats de code ?


2 commentaires

Le lien de téléchargement est cassé, vous n'arrivez pas à l'avoir ou à savoir si vous pouvez être trouvé partout ailleurs? (J'ai échoué à le trouver, le fichier lui-même n'était malheureusement pas récupérable d'archiver.org.)


@ Håkanlindqvist: Désolé, le lien MSDN est retiré et je n'ai aucun code source. Je crains que vous ayez besoin de lire les blogs écrits en chinois (avec l'aide de Google Translate peut-être?), Il y a quelques pièces de code dans les articles.



4
votes

D'où viennent les exprespessions, sont-ils créés neufs? S'ils sont réutilisés, vous pouvez simplement utiliser l'expression elle-même comme clé.:

internal static class ExpressionCache<T>
{
    private static readonly Dictionary<Expression<Func<T>, Func<T>> Cache = new Dictionary<Expression<Func<T>, Func<T>>();

    public static Func<T> CachedCompile(Expression<Func<T>> targetSelector)
    {
        Func<T> cachedFunc;
        if (!Cache.TryGetValue(targetSelector, out cachedFunc))
        {
            cachedFunc = targetSelector.Compile();
            Cache[targetSelector] = cachedFunc;
        }

        return cachedFunc;
    }
}

p>ELLSE Vous pouvez vous attaquer au code source du DLR http://dlr.codeplex.com/ , je crois qu'ils abordent ce genre de questions très bien. p> p>


0 commentaires

2
votes

au lieu d'utiliser un dictionnaire code>, si vous êtes plus préoccupé par les conditions de course et la lisibilité que sur la performance (je ne suis pas sûr si cela sera pire), vous pourriez envisagez d'utiliser un concurrentdictionner code>.

Il a déjà une méthode getoradd code> qui vous permet d'écrire moins de code, et comme il est livré avec .NET 4.0 c'est garanti. Pour travailler et être bien documenté. P>

var dict = new ConcurrentDictionary<Expression<Func<T>, Func<T>>();
...
var cacheKey = targetSelector; //or whatever as long as it's unique
var cachedFunc = dict.GetOrAdd(cacheKey, key => targetSelector.Compile());


0 commentaires