Ajout de nouveaux services Web
Remonter à Conception de serveurs gérant les services Web
Pour ajouter une nouvelle interface de service Web à votre application serveur, choisissez Fichier > Nouveau > Autre et sur la page Services Web, double-cliquez sur l'icône Interface serveur SOAP.
L'expert d'ajout de nouveau service Web vous permet de spécifier le nom de l'interface invocable que vous souhaitez afficher aux clients, et il génère le code pour déclarer et recenser l'interface et sa classe d'implémentation. Par défaut, l'expert génère également les commentaires qui montrent des exemples de méthodes et des définitions de types supplémentaires, pour vous aider à démarrer la modification des fichiers générés.
Modification du code généré
Les définitions d'interfaces apparaissent dans la section interface de l'unité générée. Cette unité générée porte le nom spécifié à l'aide de l'expert. Vous pouvez modifier la déclaration d'interface en remplaçant les exemples de méthodes par les méthodes que vous mettez à la disposition des clients.
L'expert génère une classe d'implémentation qui dérive de Soap.InvokeRegistry.TInvokableClass et qui prend en charge l'interface invocable. Si vous êtes en train de définir une interface invocable de toutes pièces, vous devez modifier la déclaration de la classe d'implémentation conformément aux modifications que vous avez apportées à l'interface invocable générée.
Lors de l'ajout de méthodes à l'interface invocable et à la classe d'implémentation, rappelez-vous que les méthodes doivent uniquement utiliser des types distants. Pour plus d'informations sur les types distants et les interfaces invocables, voir Utilisation de types non scalaires dans des interfaces invocables.
Utilisation d'une classe de base différente
L'expert Ajout d'un nouveau service Web génère des classes d'implémentation qui dérivent de TInvokableClass. Il s'agit de la manière la plus simple de créer une nouvelle classe pour implémenter un service Web. Vous pouvez toutefois remplacer cette classe générée par une classe d'implémentation avec une classe de base différente (par exemple, vous pouvez souhaiter utiliser une classe existante comme classe de base.) Un certain nombre de considérations sont à prendre en compte lorsque vous remplacez la classe d'implémentation générée :
- Votre nouvelle classe d'implémentation doit directement prendre en charge l'interface invocable. Le registre d'invocation avec lequel vous recensez les interfaces invocables et leurs classes d'implémentation conserve la trace de la classe qui implémente chaque interface recensée et la met à la disposition du composant invocateur lorsque celui-ci a besoin d'appeler l'interface. Il peut uniquement détecter qu'une classe implémente une interface si celle-ci est directement incluse dans la déclaration de la classe. Il ne détecte pas la prise en charge d'une interface si elle est héritée avec une classe de base.
- Votre nouvelle classe d'implémentation doit inclure la prise en charge des méthodes IInterface qui font partie de toute interface. Ce point peut sembler évident, mais il est facilement négligé.
- Vous devez modifier le code généré qui recense la classe d'implémentation afin d'inclure une méthode de fabrication pour créer des instances de votre classe d'implémentation.
Ce dernier point demande un peu d'explication. Lorsque la classe d'implémentation dérive de TInvokableClass et ne remplace pas le constructeur hérité par un nouveau constructeur avec un ou plusieurs paramètres, le registre d'invocation sait comment créer des instances de la classe lorsqu'il en a besoin. Lorsque vous écrivez une classe d'implémentation qui ne dérive pas de TInvokableClass ou lorsque vous modifiez le constructeur, vous devez indiquer au registre d'invocation comment obtenir des instances de votre classe d'implémentation.
Vous pouvez indiquer au registre d'invocation comment obtenir des instances de votre classe d'implémentation en lui fournissant une procédure de fabrication. Même si vous disposez d'une classe d'implémentation qui dérive de TInvokableClass et qui utilise le constructeur hérité, vous pouvez de toute façon vouloir fournir une procédure de fabrication. Par exemple, vous pouvez utiliser une instance globale unique de votre classe d'implémentation plutôt que de demander au registre d'invocation de créer une nouvelle instance chaque fois que votre application reçoit un appel à l'interface invocable.
La procédure de fabrication doit être de type TCreateInstanceProc. Elle renvoie une instance de votre classe d'implémentation. Si la procédure crée une nouvelle instance, l'objet d'implémentation doit se libérer lui-même quand le compteur de références à ses interfaces devient nul, car le registre d'invocation ne libère pas explicitement les instances d'objets. Le code suivant illustre une autre approche, dans laquelle la procédure de fabrication renvoie une instance globale unique de la classe d'implémentation :
Delphi:
procedure CreateEncodeDecode(out obj: TObject);
begin
if FEncodeDecode = nil then
begin
FEncodeDecode := TEncodeDecode.Create;
{save a reference to the interface so that the global instance doesn't free itself }
FEncodeDecodeInterface := FEncodeDecode as IEncodeDecode;
end;
obj := FEncodeDecode; { return global instance }
end;
C++:
void __fastcall CreateEncodeDecode(System::TObject* &obj)
{
if (!FEncodeDecode)
{
FEncodeDecode = new TEncodeDecodeImpl();
// save a reference to the interface so that the global instance doesn't free itself
TEncodeDecodeImpl->QueryInterface(FEncodeDecodeInterface);
}
obj = FEncodeDecode;
}
Remarque : Dans cet exemple, FEncodeDecodeInterface est une variable de type IEncodeDecode.
Le recensement de la procédure de fabrication avec une classe d'implémentation s'effectue en la spécifiant comme deuxième paramètre lors de l'appel qui recense la classe avec le registre d'invocation. Tout d'abord, localisez l'appel généré par l'expert pour le recensement de la classe d'implémentation. Il apparaît dans la section initialisation de l'unité qui définit la classe. Il a la forme suivante :
Delphi:
InvRegistry.RegisterInvokableClass(TEncodeDecode);
C++:
InvRegistry()->RegisterInvokableClass(__classid(TEncodeDecodeImpl));
Ajoutez un deuxième paramètre à cet appel pour spécifier la procédure d'appel :
Delphi:
InvRegistry.RegisterInvokableClass(TEncodeDecode, CreateEncodeDecode);
C++:
InvRegistry()->RegisterInvokableClass(__classid(TEncodeDecodeImpl), &CreateEncodeDecode);