|
Interface d'activation |
|
La définition d'une interface d'activation personnalisée et son implémentation vont nous permettre de passer des arguments lors de la création d'un objet COM. Cet article montre comment créer une telle interface avec Delphi, et par suite le moyen d'implémenter le modèle de conception singleton en programmation COM. Lorsque l'on crée un objet automation avec l'assistant de l'EDI Delphi, l'unité comprenant la déclaration de la nouvelle CoClasse, TTest par exemple, a, dans sa clause initialization, une instruction de la forme : TAutoObjectFactory.Create(ComServer, TTest, Class_Test, ciMultiInstance, tmApartment); Cette instruction crée au démarrage du serveur une instance de TAutoObjectFactory enregistrée comme étant l'usine de classe (ou fabrique d'objets) qui sert à créer des objets TTest. TAutoObjectFactory implémente en particulier l'interface COM IClassFactory. Lorsqu'un client cherche à obtenir un pointeur d'interface sur un nouvel objet COM, que se soit par un appel indirect à CreateComObject ou par la fonction CreateOleObject, c'est la fonction de haut niveau CoCreateInstance de l'API Windows qui est appelé. Celle-ci détermine quel est le fabriquant de classe associé à l'objet demandé et obtient un pointeur d'interface IClassFactory de manière à invoquer sa méthode CreateInstance pour créer un nouvel objet. Malheureusement il n'est pas possible de passer des arguments à CreateInstance pour avoir l'équivalent d'un constructeur de classe. Le reste de cet article vous conduit pas à pas dans l'implémentation d'une interface personnalisée d'activation. Les codes source peuvent être obtenus dans la section Ressources en fin d'article. Création d'un objet automation Dans l'EDI Delphi, créez une nouvelle application Project1, puis ajouter un nouvel objet automation avec comme nom de CoClasse "Test". Nous enregistrons avec le nom Test l'unité générée par Delphi et comprenant la définition de la classe Test dérivée de TAutoObject et supportant l'interface ITest. A des fins de test, nous définissons la propriété Message de type BSTR (WideString) pour l'interface ITest avec l'éditeur de la bibliothèque de types du projet. Nous nous contenterons de lire ou de modifier la variable privée FMessage de TTest. Création et implémentation de l'interface personnalisée d'activation Nous souhaitons définir une interface personnalisée nommée ITestFactory dont une des méthodes nous permettra d'instancier des objets TTest en lui passant une chaîne de caractères unicode en argument et renvoyant un pointeur d'interface ITest. En Pascal Objet : function CreateTest(const Message: WideString): ITest; safecall; Pour cela nous créons dans l'éditeur de la bibliothèque de types une nouvelle interface qui hérite de IUnknown et lui ajoutons la méthode décrite ci-dessus. Il nous reste à définir la fabrique de classe supportant l'interface ITestFactory. Nous pouvons nous appuyer sur la classe TAutoObjectFactory : TTestFactory = class(TAutoObjectFactory, ITestFactory) protected function CreateTest(const Message: WideString): ITest; safecall; end; La méthode CreateTest se contente d'instancier un object TTest sous forme du pointeur d'interface ITest : function TTestFactory.CreateTest(const Message: WideString): ITest; begin Result := TTest.Create(Message) as ITest; end; Enregistrement de la fabrique de classe Dans la clause initialization de l'unité Test, nous remplaçons l'instruction TAutoObjectFactory.Create(...) par TTestFactory.Create(...). Cela a pour conséquence d'enregistrer TTestFactory comme fabrique de classe pour la classe TTest au lieu de TAutoObjectFactory qui aurait instancié des objets TTest à l'aide de IClassFactory. Au démarrage du serveur, une instance de notre fabrique de classe est donc créée et enregistrée. Accéder à la fabrique de classe Une application cliente peut obtenir une référence vers l'instance enregistrée de la fabrique de classe du serveur à l'aide de la méthode GetObject définie dans l'unité ActivationObject. Le serveur servant de test, Project1, doit bien sûr être recenser au préalable, soit en l'exécutant une première fois, soit en l'exécutant avec l'argument /regserver. Cette fonction prend comme unique argument un GUID devant être celui de la classe pour laquelle celle-ci renvoie un fabriquant de classe. Dans notre exemple, c'est la constante CLASS_Test de la bibliothèque de types. GetObject renvoie une référence IUnknown qui peut ensuite être transtypée en ITestFactory à l'aide de l'opérateur as. Le programme de test, Project1, du répertoire Client utilise donc la fabrique de classe de TTest pour instancier un objet TTest avec la méthode ITestFactory.CreateTest, de la manière suivante : var TestFactory: ITestFactory; begin TestFactory := GetObject(CLASS_Test) as ITestFactory; Test := TestFactory.CreateTest(Edit1.Text); // Test est de type ITest end; La fonction GetObject (nom d'une fonction équivalente en Visual Basic) est implémentée un utilisant un moniker de classe. La description des monikers déborde du cadre de cet article. Singleton COM L'utilisation d'une interface personnalisée d'activation permet l'implémentation du modèle de conception singleton en programmation COM. En effet, une fonction telle que CreateTest pourrait toujours renvoyer la même instance d'objet créée une seule fois dans le fabriquant de classe, au premier appel de cette méthode. Ressources Téléchargez les programmes d'exemple |
SommaireCréation d'un objet automation Création et implémentation de l'interface personnalisée d'activation Enregistrement de la fabrique de classe Accéder à la fabrique de classe Singleton COM Ressources |
Début |
Copyright © 2003 OBJECT-EVERYWHERE. Tous droits réservés | Bertrand Goetzmann |