Bonjour,
Aprés les différentes discussion à propos des interfaces, une question est apparue dans ma petite tête. Et si un objet pouvait supporter des interfaces de façon dynamique et servir ainsi de concentrateur de tous les délégués?...hum interessant...non?
Voici comment j'ai implémenté ça:
une optimisation possible serait de créer une liste clé/valeur pour remplacer la liste d'interfaces.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 unit IntfUnt; interface uses Classes, SysUtils; type ISupportDynamique = interface ['{0770742D-FAB0-4027-A31E-D704F4142BF3}'] procedure EnregistrerObjet(const IID: TGUID; const ImplObj: IInterface); procedure SupprimerTousLesObjets; end; function NouveauSupportDynamique: ISupportDynamique; implementation type TSupportDynamique = class(TInterfacedObject, IInterface, ISupportDynamique) private FIntfs: IInterfaceList; //liste clé/valeur (string -> obj) serait mieux ici protected function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; procedure EnregistrerObjet(const IID: TGUID; const ImplObj: IInterface); procedure SupprimerTousLesObjets; public constructor Create; end; IInfoObjet = interface ['{1EAFA560-8D8D-4743-B960-C0694DA23D28}'] function ObjetImplementeur: IInterface; end; TInfoObjet = class(TInterfacedObject, IInfoObjet) private FObjet: IInterface; private function ObjetImplementeur: IInterface; public constructor Create(const ObjetImplementeur: IInterface); end; function NouveauSupportDynamique: ISupportDynamique; begin Result := TSupportDynamique.Create; end; { TSupportDynamique } constructor TSupportDynamique.Create; begin inherited Create; FIntfs := TInterfaceList.Create; end; procedure TSupportDynamique.EnregistrerObjet(const IID: TGUID; const ImplObj: IInterface); var info: IInfoObjet; begin info := TInfoObjet.Create(ImplObj); FIntfs.Add(info); end; function TSupportDynamique.QueryInterface(const IID: TGUID; out Obj): HResult; var temp: IInterface; info: IInfoObjet; i: integer; begin Result := E_NOINTERFACE; if GetInterface(IID, Obj) then begin Result := S_OK; Exit; end; //ici idéalement une liste GUID -> Obj plutôt que IInterfaceList FIntfs.Lock; try for i := 0 to FIntfs.Count - 1 do begin info := FIntfs.Items[i] as IInfoObjet; if not Assigned(info) then Exit; temp := info.ObjetImplementeur; if Supports(temp, IID, Obj) then begin Result := S_OK; Exit; end; end; finally FIntfs.Unlock; end; end; procedure TSupportDynamique.SupprimerTousLesObjets; begin FIntfs.Clear; end; { TInfoObjet } constructor TInfoObjet.Create(const ObjetImplementeur: IInterface); begin inherited Create; FObjet := ObjetImplementeur; end; function TInfoObjet.ObjetImplementeur: IInterface; begin Result := FObjet; end; end.
utilisation:
j'ai crée 2 unités simple definissant 2 interfaces ISalut et IBonjour
et ISalut
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 unit BonjourIntf; interface uses Dialogs; type IBonjour = interface ['{B1B342C7-28D0-4CED-BAC3-748D87153F48}'] procedure Bonjour; end; function NouveauBonjour: IBonjour; implementation type TBonjour = class(TInterfacedObject, IBonjour) procedure Bonjour; end; function NouveauBonjour: IBonjour; begin Result := TBonjour.Create; end; { TBonjour } procedure TBonjour.Bonjour; begin ShowMessage('Bonjour'); end; end.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 unit SalutIntf; interface uses Dialogs; type ISalut = interface ['{CA2EB942-4DEA-4315-9E51-7954182D2661}'] procedure Salut; end; function NouveauSalut: ISalut; implementation type TSalut = class(TInterfacedObject, ISalut) procedure Salut; end; function NouveauSalut: ISalut; begin Result := TSalut.Create; end; { TSalut } procedure TSalut.Salut; begin ShowMessage('Salut'); end; end.
dans ma fiche principale, je crée un ISupportDynamique et je lui enregistre un ISalut et IBonjour
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14FDynaObj: ISupportDynamique; (...) procedure TForm5.FormCreate(Sender: TObject); begin FDynaObj := NouveauSupportDynamique; FDynaObj.EnregistrerObjet(ISalut, NouveauSalut); FDynaObj.EnregistrerObjet(IBonjour, NouveauBonjour); end;
maintenant que les objets sont enregistrer, je peut accéder au service ISalut et IBonjour comme ceci.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 (FDynaObj as ISalut).Salut; (FDynaObj as IBonjour).Bonjour;
FDynaObj implémente maintenant ISalut et IBonjour par délégation
Commentaires, critiques, améliorations, pièce de 5 centimes......sont acceptés![]()








Répondre avec citation
Partager