Programmation orientée aspect avec Autofac et DynamicProxy

Auteur du billet de blog : Nicolas Hilaire - Neotech Solutions

Nicolas Hilaire

Consultant .NET
  Publié le mardi 18 octobre 2016

Artisan logiciel particulièrement intéressé par les technologies .NET. Polyvalent et curieux, je suis néanmoins à l'écoute des autres technologies du marché. MVP (Microsoft Most Valuable Professional) de 2007 à 2014, je suis également auteur d'un ouvrage pour apprendre le C#, à destination des débutants et de plusieurs MOOCs sur le C#, Windows Phone ou ASP.NET MVC...

Dans ce billet, nous allons voir une solution pour faire de la programmation orientée aspect avec Autofac et DynamicProxy du projet Castle.

Qu’est-ce que l’AOP ?

L’AOP (Aspect-oriented programming), que l’on peut traduire par programmation orientée aspect, est un paradigme de programmation qui permet de traiter des problématiques (souvent) techniques de manière transverse, sans impacter le code métier. Le but est de réduire le couplage entre ces éléments techniques et le code métier, tout en améliorant la réutilisabilité et la qualité du code.

On illustre ce point souvent avec le log. En développant de manière « classique », on a souvent du code de ce genre :

 

 

Et même si ce code utilise une abstraction pour ne pas être fortement couplée à la classe de log, on est quand même obligé d’appeler les méthodes de log directement dans le corps de MaMethode, alors que ce n’est pas vraiment son rôle.

(A noter que pour ne pas mélanger le code métier de MaMethode, il est possible d’utiliser un décorateur pour ajouter un comportement de log sur la classe, mais cela a l’inconvénient de rajouter une nouvelle classe et une nouvelle abstraction)

L’AOP nous propose une autre façon de faire en faisant ce qu’on appelle un tissage, soit dynamique, soit statique :

  • Le tissage statique est réalisé en injectant du code MSIL directement à la compilation.
  • Le tissage dynamique est réalisé en utilisant des classes proxys

En .NET, on voit souvent l’AOP associé à des attributs permettant de décorer les méthodes. Par exemple, on peut placer sur un contrôleur MVC ou Web API (ou sur une méthode du contrôleur) un attribut [Authorize] permettant de dire que ce contrôleur (ou méthode) sera soumis à authentification ; le code faisant ça étant exécuté de manière transverse par le Framework.

 

AOP avec Autofac et DynamicProxy

Il existe plusieurs bibliothèques pour faire de l’AOP, je vais vous montrer ici comment utiliser DynamicProxy du projet castle avec Autofac. Comme le nom le suggère, nous allons faire ici du tissage dynamique.

Pour l’exemple, nous allons construire une brique technique qui permet de mesurer le temps d’exécution d’une méthode.

Voici la méthode que je souhaite mesurer :

 

 

La première chose à faire est de référencer le package Nuget Autofac.Extras.DynamicProxy2 :

 

 

Pour faire notre mesure, on va créer un interceptor, en implémentant l’interface IInterceptor :

 

 

Cet intercepteur doit implémenter la méthode Intercept prenant en paramètre un IInvocation. Cet objet nous fournit des informations sur la méthode interceptée (comme son nom (invocation.Method), ou ses paramètres, etc.) mais aussi la possibilité de l’invoquer avec la méthode Proceed. Et c’est bien sûr cette méthode que je vais entourer d’un Stopwatch me permettant d’en mesurer le temps d’exécution.

Comme je ne voulais pas faire un n-ième intercepteur qui logue dans la console, j’ai créé une classe de Log basique et je m’en sers pour loguer le temps d’exécution de la méthode :

 

 

La plomberie est quasiment terminée. Il faut maintenant déclarer l’intercepteur dans le conteneur IOC et lui dire quelle classe il doit intercepter :

 

 

Ici, j’enregistre mon Service, en le déclarant candidat à l’interception (EnableClassInterceptors) et intercepté par la classe MeasureTimeLogger. Vous devez bien sûr au passage enregistrer le logueur ainsi que la classe d’interception.

Et il y a une ultime chose à faire, et oh combien indispensable ; et ceci est lié à la nature du tissage que nous allons utiliser. Comme DynamicProxy va créer des proxys dynamiques, il faut absolument que les méthodes candidates à l’interception soient éligibles à la substitution. Et pour cela, nous devons les marquer virtual. Notre service devient donc :

 

 

Et voilà, vous pouvez exécuter votre code, un log avec le temps d’exécution sera automatiquement créé lors de l’appel à la méthode DoSomething.

 

Créer une méthode avec retry automatique

On peut faire des trucs sympas avec ces intercepteurs, comme par exemple un retry automatique :

 

 

Ici, j’ai une méthode qui plante aléatoirement, et grâce à mon intercepteur qui fait un retry automatique 5 fois de la méthode, j’ai une chance qu’elle passe :).

 

 

Conclusion

Voilà pour ce petit billet qui constitue une introduction à l’AOP avec DynamicProxy et Autofac. A noter qu’il existe d’autres bibliothèques permettant de faire de l’injection de code MSIL comme Postsharp, il s’agit cependant d’un produit commercial.