Je lisais des articles sur la mise en cache et la mémorisation et comment les mettre en œuvre facilement en utilisant des délégués et des génériques. La syntaxe était assez simple, et il est étonnamment facile à implémenter, mais je pense juste à cause de la nature répétitive qu'il devrait être possible de générer du code basé sur un attribut, au lieu de devoir écrire le même code de plomberie encore et encore.Comment injecter/générer du code de plomberie dans des méthodes décorées avec un attribut?
Disons que nous commençons par l'exemple par défaut:
class Foo
{
public int Fibonacci(int n)
{
return n > 1 ? Fibonacci(n-1) + Fibonacci(n-2) : n;
}
}
Et puis memoize ceci:
// Let's say we have a utility class somewhere with the following extension method:
// public static Func<TResult> Memoize<TResult>(this Func<TResult> f)
class Foo
{
public Func<int,int> Fibonacci = fib;
public Foo()
{
Fibonacci = Fibonacci.Memoize();
}
public int fib(int n)
{
return n > 1 ? Fibonacci(n-1) + Fibonacci(n-2) : n;
}
}
Je pensais, ça ne serait pas plus simple de faire un générateur de code crache ce code, une fois qu'il trouve une méthode étiquetée qui correspond à l'une des méthodes d'extension Memoize. Donc, au lieu d'écrire ce code de plomberie, je pourrais simplement ajouter un attribut:
class Foo
{
[Memoize]
public int Fibonacci(int n)
{
return n > 1 ? Fibonacci(n-1) + Fibonacci(n-2) : n;
}
}
Honnêtement, je sais que cela ressemble de plus comme le sucre du compilateur qui doit être converti par un préprocesseur que la génération de code réel, mais ma question est:
- que pensez-vous est la meilleure façon de trouver les méthodes dans le fichier source aC# qui ont un attribut donné, l'analyse syntaxique les parametertypes et returntype, et la génération d'un délégué qui correspond à cette empreinte
- Quelle serait la meilleure façon d'intégrer cela dans le processus de construction, sans réellement sur écrire mon code. Est-il possible de faire un pré-traitement sur les fichiers sources avant de les transmettre au compilateur?
Merci pour toutes les idées.
Mise à jour:
J'ai regardé dans la bibliothèque PostSharp que Shay avait suggéré, et il semblait très adapté pour le travail sur des applications non critiques comme la gestion des transactions, traçage ou de sécurité. Cependant, en l'utilisant dans un contexte critique, il s'est avéré beaucoup plus lent que le délégué. Un million d'itérations de l'exemple Fibonacci avec chaque implémentation a entraîné une exécution 80 fois plus lente. (0.012ms postsharp vs 0.00015ms délégué par appel)
Mais honnêtement, le résultat est tout à fait acceptable dans le contexte dans lequel j'ai l'intention de l'utiliser. Merci pour les réponses!
Update2:
Apparemment, l'auteur de PostSharp travaille dur sur un release 2.0 qui comprendra, entre autres, l'amélioration des performances dans le code produit, et la compilation.
Cela ressemble à une très bonne alternative. Je vais y regarder. –
J'ai voté pour celui-ci, mais je suis peut-être un peu partial :). –
@Patrick, donc vous faites tout le travail et je reçois les votes :) –