Présentation des interfaces invocables
Remonter à Utilisation de services Web - Index
Les serveurs qui gèrent les services Web sont construits à l'aide d'interfaces invocables. Ces interfaces sont des interfaces compilées afin de contenir des informations de type à l'exécution (RTTI). Sur le serveur, ces informations sont utilisées pour interpréter les appels de méthodes entrants des clients afin de pouvoir les répartir correctement. Côté client, ces informations sont utilisées pour générer dynamiquement une table des méthodes permettant d'effectuer des appels aux méthodes de l'interface.
Pour créer une interface invocable, il vous suffit de compiler une interface avec l'option de compilation {$M+}. Le descendant de toute interface invocable est également invocable. Cependant, si une interface invocable descend d'une autre classe qui n'est pas invocable, votre service Web peut utiliser uniquement les méthodes définies dans l'interface invocable et dans ses descendants. Les méthodes héritées d'ancêtres non invocables ne sont pas compilées avec les informations de type et ne peuvent donc pas être utilisées comme partie du service Web.
Lorsque vous définissez un service Web, vous pouvez dériver une interface invocable à partir de l'interface invocable de base, System.IInvokable. IInvokable est définie dans l'unité System. IInvokable est identique à l'interface de base (IInterface), sauf qu'elle est compilée en utilisant l'option de compilation {$M+}. Grâce à l'option de compilation {$M+}, l'interface et tous ses descendants contiennent les informations RTTI.
Par exemple, le code suivant définit une interface invocable contenant deux méthodes pour coder et décoder des valeurs numériques :
IEncodeDecode = interface(IInvokable) ['{C527B88F-3F8E-1134-80e0-01A04F57B270}'] function EncodeValue(Value: Integer): Double; stdcall; function DecodeValue(Value: Double): Integer; stdcall; end;
__interface INTERFACE_UUID("{C527B88F-3F8E-1134-80e0-01A04F57B270}") IEncodeDecode : public IInvokable { public: virtual double __stdcall EncodeValue(int Value) = 0 ; virtual int __stdcall DecodeValue(double Value) = 0 ; };
Remarque : Une interface invocable peut utiliser des méthodes redéfinies, mais uniquement si les différentes redéfinitions peuvent être différenciées par leur décompte de paramètres. Ainsi, une redéfinition ne doit pas posséder le même nombre de paramètres qu'une autre, y compris le nombre possible de paramètres lorsque les paramètres par défaut sont pris en compte.
Pour qu'une application service Web puisse utiliser cette interface invocable, elle doit être recensée dans le registre d'invocation. Sur le serveur, l'entrée du registre d'invocation permet aux composants invocateur (Soap.SOAPHTTPPasInv.THTTPSoapPascalInvoker) d'identifier la classe d'implémentation à utiliser pour l'exécution des appels de l'interface. Dans les applications client, une entrée du registre d'invocation permet aux objets interfacés distants (Soap.SOAPHTTPClient.THTTPRIO) de rechercher les informations identifiant l'interface invocable et fournit des informations sur la manière de l'appeler.
Généralement, votre client ou serveur de service Web crée le code de définition des interfaces invocables en important un document WSDL ou en utilisant l'expert de service Web. Par défaut, lorsque l'importateur WSDL ou l'expert de service Web génère une interface, la définition est ajoutée à l'unité avec le même nom que le service Web. Cette unité comprend la définition de l'interface et le code permettant de recenser l'interface dans le registre d'invocation. Le registre d'invocation est un catalogue de toutes les interfaces invocables recensées, de leurs classes d'implémentation et des fonctions qui créent des instances de ces classes d'implémentation. Il est accessible via la fonction globale InvRegistry, définie dans l'unité InvokeRegistry.
La définition de l'interface invocable est ajoutée à la section interface de l'unité, et le code permettant de recenser l'interface figure dans la section initialisation. Le code de recensement présente l'aspect suivant :
initialization InvRegistry.RegisterInterface(TypeInfo(IEncodeDecode)); end.
static void RegTypes() { InvRegistry()->RegisterInterface(__delphirtti(IEncodeDecode), "", ""); } #pragma startup RegTypes 32
Remarque : La clause uses de la section implémentation doit comprendre l'unité InvokeRegistry afin que l'appel de la fonction InvRegistry soit défini.
Les interfaces de services Web doivent posséder un espace de nommage pour identifier toutes les interfaces dans tous les services Web possibles. L'exemple précédent ne fournit pas d'espace de nommage pour l'interface. Lorsque vous ne fournissez pas explicitement un espace de nommage, le registre d'invocation en génère automatiquement un à votre place. Cet espace de nommage est créé à partir d'une chaîne qui identifie de manière unique l'application (la variable AppNamespacePrefix variable), le nom de l'interface et le nom de l'unité dans laquelle elle est définie. Si vous ne souhaitez pas utiliser l'espace de nommage généré automatiquement, vous pouvez en spécifier un explicitement en utilisant un deuxième paramètre lors de l'appel à RegisterInterface.
Vous pouvez utiliser le fichier unité pour définir une interface invocable à la fois pour les applications client et pour les applications serveur. Dans ce cas, il est judicieux d'utiliser, pour définir les interfaces invocables, une unité distincte de celle utilisée pour les classes d'implémentation des interfaces. Comme l'espace de nommage généré contient le nom de l'unité dans laquelle l'interface est définie, le partage de la même unité dans les applications serveur et client permet d'utiliser automatiquement le même espace de nommage, sous réserve qu'elles utilisent la même valeur pour la variable AppNamespacePrefix.
L'exemple précédent n'utilise que des types scalaires (entiers et doubles) dans les méthodes de l'interface. Vous pouvez également utiliser des types non scalaires, mais cela nécessite un peu plus de travail.