Accès aux propriétés (par leur nom) des composants
en cours d’exécution grâce au Run Time Type Information

 

  Imaginons que l’on souhaite changer la propriété dataSource d’un ensemble de composants
basés présents sur un formulaire.

On pourrait penser que tous les composants basés (ex : TDbEdit, TDbText…) ont un ancêtre
commun possédant la propriété DataSource. Le polymorphisme nous permettrait alors
d’accéder pour chacun des composants à sa propriété DataSource en le ‘castant’ avec le type
de cet ancêtre commun.

Si la classe de cet ancêtre commun s’appelait Tbased, cela pourrait donner par exemple le
code suivant :

Procedure Tform1.SetDataSource(DataSource : TdataSource) ;
Var iIndex : integer ;
Begin

For iIndex := ComponentCount-1 downto 0 do
Tbased(Components[iIndex]).DataSource := DataSource ;
End ;

En réalité, les composants basés ont pour ancêtre leur pendant non basé. Ainsi un TDbEdit
hérite d’un TEdit, tandis qu’un TDbText hérite d’un TText. Delphi ne permettant pas
l’héritage multiple, il n’a donc pas été possible de placer un ancêtre commun aux composants
basés. Si donc on souhaite changer la propriété dataSource de tous les composants basés d’un
formulaire, il faut soit exécuter une suite impressionnante de if jusqu’à tomber sur la bonne
classe afin de pouvoir ‘caster’ le composant, soit utiliser le RTTI (RunTimeTypeInformation)
afin d’accéder à la propriété du composant.

La premiére solution (fastidieuse) serait du style :

Procedure Tform1.SetDataSource(DataSource : TdataSource) ;
Var iIndex : integer ;
Begin

For iIndex := ComponentCount-1 downto 0 do
Begin
If Components[iIndex] is tdbEdit then TdbEdit(Components[iIndex]).DataSource := DataSource ;
If Components[iIndex] is tdbText then TdbEdit(Components[iIndex]).DataSource := DataSource ;
. . . . . . .
If Components[iIndex] is tdbTruc then TdbTruc(Components[iIndex]).DataSource := DataSource ;
End;
End

En utilisant le RTTI, on obtient une solution compacte et générique :

Procedure Tform1.SetDataSource(DataSource : TdataSource) ;
Var iIndex : integer ;

PropInfo : ppropInfo ; Begin
For iIndex := ComponentCount-1 downto 0 do
begin
PropInfo := GetPropInfo(Components[iIndex].classInfo, ‘DataSource’) ;
If propInfo <> nil then
setOrdProp(Components[iIndex], PropInfo, Integer(DataSource));
end
End

!! il faut penser à ajouter typInfo dans le uses.

Les informations contenues dans le RTTI sont créées par le compilateur Delphi et sont
disponibles au run time pour le programmeur. Elles sont en outre largement utilisées au
design par l’inspecteur d’objets par exemple.