| Custom Proxy dans .NET Remoting |
|
(version
Imprimable) Le but de cet article est de vous permettre d'intercepter les appels vers des objets distants afin d'effectuer un traitement spécifique. Nous utiliserons pour cela le code du serveur Hello écrit dans un arcticle précédent (.NET Remoting vs RMI). Qu'est-ce qu'un Proxy .NET Remoting ? Les proxy sont des objets créés lorsque le client active un objet distant. Il agit comme la représentation locale d'un objet distant et assure que tous les appels effectués sur le Proxy sont acheminés vers ce dernier. Lorsque le client active un objet distant, le Framework crée une instance locale de la classe TransparentProxy aussitôt chargée dans la CLR. Tous les appels de méthodes sont interceptés par le Runtime. Ainsi, l'appel est analysé dans le but de déterminer si la méthode est valide et si une instance de l'objet distant réside dans le même domaine d'application en tant que Proxy. Si c'est le cas, un appel direct in-process est effectué vers l'objet en question (correspond aux "client activated objects"). Cela évite d'avoir le surcoût correspondant à un appel distribué alors que l'objet est local. Ce problème est bien connu des développeurs RMI et correspond aux EJB locaux dans la spécification EJB 2.0. Si l'objet se trouve dans un domaine d'application différent, les paramètres d'appels sur la pile sont emballés dans un objet de type IMessage et transférés à la classe RealProxy en utilisant sa méthode invoke(). Il existe une implémentation par défaut de cette classe consistant à transférer l'appel vers l'objet distant. Le code suivant nous illustre l'opération réalisée dans la méthode : Activator.GetObject()
Implémenter un Custom Proxy TransparentProxy et RealProxy sont créés de manière interne lorsque l'objet est activé mais seul le TransparentProxy est renvoyé au client par l'intermédiaire de la méthode GetTransparentProxy() de l'objet RealProxy. L'idée ici, consistera à développer notre propre classe RealProxy et à l'instancier. Le schéma suivant vous illustre les différentes étapes intervenant dans la chaîne d'invocation d'une méthode distante via Remoting.
La classe TransparentProxy est une classe interne ne pouvant être enrichie ou étendue. La classe RealProxy servira à cet effet. Ainsi, dans le cas où vous souhaiteriez implémenter les fonctionnalités suivantes : - La répartition de charge : il suffira de tester dans notre Custom Proxy si tel ou tel serveur est chargé dans le but de répartir efficacement les traitements - L'interception des paramètres pour ajouter certaines informations (traduction linguistique des chaînes de caractères en temps réel ;-) par exemple) - Etendre les fonctionnalités de sécurité existantes pour acheminer uniquement les appels vers les serveurs auprès desquels le client est authentifié, etc. ... Nous allons donc écrire un MyRealProxy qui dérivera de la classe RealProxy et redéfinir la méthode invoke(). Ensuite, il faudra faire en sorte que le client utilise notre classe de manière aussi transparente que possible. Il existe deux façons de procéder : - En interceptant l'opération new à l'aide d'un attribut ProxyAttribute - En réalisant l'opération de construction manuellement dans le code du client à l'aide de l'instruction new RealProxy() Nous choisirons la dernière solution par soucis de simplicité. Voici le code Client :
Le client se charge de créer l'objet MyProxy et d'effectuer l'appel à l'aide du TransparentProxy. Regardons maintenant le code tant attendu de la classe MyRealProxy.
Explications Quelques explications sont cependant nécessaires même si
seule la méthode invoke() est pertinente dans cet exemple. Lors de la
construction du Proxy, nous nous chargeons d'envoyer le type de l'objet distant
à la classe mère (base(t)). Cette dernière a besoin de cette information
capitale afin d'implémenter correctement la méthode GetTransparentProxy())
pour renvoyer un proxy correspondant au bon type. Ensuite, un chaineur de
message (MessageSink) correspondant à
notre channel est recherché et créé. Un chaîneur est un objet permettant de
déléguer l'appel au Framework en utilisant plusieurs classes chaînées
entre-elles. Cela vous permet de redéfinir vous même votre chaîneur afin
d'effectuer des appels spécifiques (asynchrones, ...). Vous trouverez
ici
un exemple de chaîneur pertinent redéfinit pour permettre de débogguer les
appels de méthode. Une fois le chaîneur récupéré, il ne nous reste plus qu'à
invoquer la méthode distante avec SyncProcessMessage(msg). Lors de l'exécution du Client, vous obtenez à l'écran un joli message "Coucou l'appel est intercepté" émis par votre Custom Proxy. Conclusion .NET Remoting propose un mécanisme très élaboré permettant d'effectuer des opérations d'interception de messages correspondant à l'implémentation d'un Custom Dynamic Proxy en Java. Vous savez maintenant comment faire, à vous de trouver des idées d'implémentation pertinente ! Auteur : Sami Jaber |