Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Thomas Lebrun

Tout sur WPF, LINQ, C# et .NET en général !

Actualités

[AOP] L’interception avec Unity

Unity est un container IoC très pratique mais qui offre, en plus, la possibilité de réaliser un peu d’AOP (Aspect Oriented Programming) au moyen d’une extension pour l’interception.

En gros, vous allez avoir la possibilité d’intercepter l’exécution de bouts de code (appels de méthodes virtuelles, appels de méthodes définies dans des interfaces, etc.) pour rajouter votre propre logique.

Cela peut s’avérer très pratique lorsque vous avez, par exemple, des objets métiers ou des services mais pour lesquels vous ne souhaitez qu’ils s’occupent de gérer des tâches comme la gestion de logs, la gestion des exceptions, du cache, etc.

Voyons cela avec un exemple simple: imaginer que vous vouliez être en mesure de logger le temps d’exécution des méthodes que vous avez défini dans vos Client Services ou dans vos Helpers. Pour cela, il est d’abord nécessaire de créer la classe correspondante:

   1: public interface ILogger
   2: {
   3:     void Log(string errorMessage);
   4: }
   5:  
   6: public class Logger : ILogger
   7: {
   8:     public void Log(string errorMessage)
   9:     {
  10:         // TODO: Implement method
  11:     }
  12: }

A présent, nous allons ajouter les références nécessaire à notre projet pour pouvoir utiliser Unity et l’interception, à savoir Microsoft.Practices.Unity et Microsoft.Practices.Unity.Interception. Ensuite, nous allons pouvoir écrire notre CallHandler, il s’agit de la classe qui va pouvoir nous permettre de rajouter notre propre comportement:

   1: public class LogExecutionTimeCallHandler : ICallHandler
   2: {
   3:     public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
   4:     {
   5:         var sw = new Stopwatch();
   6:         sw.Start();
   7:  
   8:         IMethodReturn result = getNext()(input, getNext);
   9:  
  10:         sw.Stop();
  11:  
  12:         Debug.WriteLine("Method {0} tooks {1}", 
  13:                 input.MethodBase.Name, 
  14:                 string.Concat(sw.Elapsed.Hours, ":", sw.Elapsed.Minutes, ":",
  15:                 sw.Elapsed.Seconds, ".", sw.Elapsed.Milliseconds));
  16:  
  17:         return result;
  18:     }
  19:  
  20:     public int Order { get; set; }
  21: }
Comme vous pouvez le voir, cette classe se contente de démarrer un chronomètre, appelle la méthode qui est demandée puis affiche le temps d’exécution dans la fenêtre de déboggage de Visual Studio.
 

Cette classe est donc celle que nous devons utilisé mais nous ne pouvons pas le faire tel quel, nous allons essayer de nous simplifier la vie au maximum, en utilisant un attribut. Dès que cet attribut sera rencontré, il utilisera une instance de notre CallHandler et notre logique de log sera appelée:

   1: public class LogExecutionTimeAttribute : HandlerAttribute
   2: {
   3:     public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
   4:     {
   5:         return new LogExecutionTimeCallHandler();
   6:     }
   7: }

Maintenant, il ne nous reste plus qu’à appliquer notre attribut sur chacune de nos méthodes, définies dans notre interface:

   1: public interface ILogger
   2: {
   3:     [LogExecutionTime]
   4:     void Log(string errorMessage);
   5: }

Dès lors, nous pouvons mettre en place notre container Unity et configurer l’interception:

   1: IUnityContainer container = new UnityContainer();
   2: container.AddNewExtension<Interception>();
   3: container.RegisterType<ILogger, Logger>().Configure<Interception>().
   4: SetInterceptorFor<ILogger>(new InterfaceInterceptor());
   5:  
   6: ILogger logger = container.Resolve<ILogger>();
   7: logger.Log("TEST");

Nous pouvons voir ici que nous utilisons un InterfaceInterceptor, afin d’indiquer à Unity que les méthodes que nous voulons intercepter sont présentes dans l’interface que j’ai spécifié (ILogger). Si nous n’avions pas utilisé d’interface pour notre helper, nous aurions pû mettre en place des méthodes virtuelles, et utiliser un VirtualMethodInterceptor.

Lors de l’exécution, la méthode Log est correctement appelé et notre chronomètre est, lui aussi, bien démarré et utilisé:

image

 

Il s’agit donc là d’une technique très pratique lorsque l’on souhaite mettre en oeuvre du log, du cache, etc. et que l’on ne désire pas implémenter ces fonctionnalités directement sur ces objets !

 

Plus d’informations: http://www.palmmedia.de/Blog/2010/9/26/aop-interception-with-unity-2.0

 

 

A+,

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: jeudi 4 août 2011 15:54 par Thomas LEBRUN
Classé sous : , , ,

Commentaires

tomlev a dit :

Sympa ! Par contre, un petit détail qui me chiffonne :

  6:         sw.Start();

  7:  

  8:         IMethodReturn result = getNext()(input, getNext);

  9:  

 10:         sw.Stop();

Avec ça le Stopwatch mesure aussi le temps d'exécution de getNext ; il faudrait appeler getNext avant de démarrer le Stopwatch, sinon le résultat est faussé...

# août 4, 2011 16:34

Thomas LEBRUN a dit :

Yep, en effet mais c'était surtout pour donner une idée de ce que l'on peut faire :)

Mais bonne remarque, merci !

# août 4, 2011 16:50

grogru a dit :

C'est cool ce truc ! :-)

# août 5, 2011 10:03
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Office 365: Nettoyage des versions de List Item avant migration depuis SharePoint On Premise vers SharePoint Online par Blog Technique de Romelard Fabrice le 08-08-2017, 15:36

- Office 365: Comment supprimer des éléments de liste SharePoint Online via PowerShell par Blog Technique de Romelard Fabrice le 07-26-2017, 17:09

- Nouveau blog http://bugshunter.net par Blog de Jérémy Jeanson le 07-01-2017, 16:56

- Office 365: Script PowerShell pour assigner des droits Full Control à un groupe défini par Blog Technique de Romelard Fabrice le 04-30-2017, 09:22

- SharePoint 20XX: Script PowerShell pour exporter en CSV toutes les listes d’une ferme pour auditer le contenu avant migration par Blog Technique de Romelard Fabrice le 03-28-2017, 17:53

- Les pièges de l’installation de Visual Studio 2017 par Blog de Jérémy Jeanson le 03-24-2017, 13:05

- UWP or not UWP sur Visual Studio 2015 ? par Blog de Jérémy Jeanson le 03-08-2017, 19:12

- Désinstallation de .net Core RC1 Update 1 ou SDK de Core 1 Preview 2 par Blog de Jérémy Jeanson le 03-07-2017, 19:29

- Office 365: Ajouter un utilisateur ou groupe dans la liste des Site collection Administrator d’un site SharePoint Online via PowerShell et CSOM par Blog Technique de Romelard Fabrice le 02-24-2017, 18:52

- Office 365: Comment créer une document library qui utilise les ContentTypeHub avec PowerShell et CSOM par Blog Technique de Romelard Fabrice le 02-22-2017, 17:06