Le code suivant permet de lister les membres de deux instances d'une même classe afin de comparer leurs valeurs respectives, en utilisant les mécanismes d'introspection et d'indirection de Windev.
Les membres testés peuvent être de type primitif (entier, chaine) ou complexe (objet, structure, tableau d'objets ou de structures).

Ceci est rendu possible par l'ajout dans Windev 17 de fonctionnalités de "Réflexion" (Reflection en Java), permettant de manipuler les objets d'une classe en énumérant leurs méthodes, leurs membres et leurs propriétés :
http://doc.pcsoft.fr/fr-fr/?6010015

Pour commencer, voici une procédure permettant d'afficher toutes les informations disponibles concernant un objet (Liste des propriétés, des membres et des méthodes) :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
 
PROCEDURE IntrospectionObjet(_oObj)
 
Def_oObj est une Définition
//Cf http://doc.pcsoft.fr/fr-fr/?1000019540&name=definition_type_variable&q=D%C3%A9finition
 
Def_oObj = RécupèreDéfinition(_oObj)                              
SI Def_oObj = Null ALORS
	Erreur(ErreurInfo(errComplet))
	RENVOYER Faux
FIN
 
TraceDefinition(Def_oObj,0,_oObj)
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
 
PROCEDURE TraceDefinition(LOCAL _Def est une Définition,_iProfondeur est un entier,LOCAL _oObj=Null)
 
sProfondeur est une chaîne
sProfondeur = Complète("",_iProfondeur*5)
 
Trace(sProfondeur+"Définition Nom : "+_Def..Nom+" | Type : "+_Def..Type+" | FamilleDéfinition : "+_Def..FamilleDéfinition)
 
_iProfondeur++
 
DescProp est une Description de Propriété
POUR TOUT DescProp DE _Def..Propriété
	TraceDescriptionPropriété(DescProp,_iProfondeur)
FIN
 
DescVar est une Description de Variable
POUR TOUT DescVar DE _Def..Variable
	TraceDescriptionVariable(DescVar,_iProfondeur,_oObj)
FIN
 
DescProc est une Description de Procédure
POUR TOUT DescProc DE _Def..Procédure
	TraceDescriptionProcédure(DescProc,_iProfondeur)
FIN
 
_iProfondeur--
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
 
PROCEDURE TraceDescriptionPropriété(DescProp,_iProfondeur est un entier)
 
sProfondeur est une chaîne
sProfondeur = Complète("",_iProfondeur*5)
 
Trace(sProfondeur+"--------------------")
Trace(sProfondeur+"Propriété :")
Trace("Nom : "+DescProp..Nom+" | Global : "+DescProp..Global+" | Hérité : "+DescProp..Hérité+" | Virtuel : "+DescProp..Virtuel+" | Lecture : "+DescProp..Lecture+" | Ecriture : "+DescProp..Ecriture)
TraceDefinition(DescProp..Déclaration,_iProfondeur)
TraceDefinition(DescProp..Définition,_iProfondeur)
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
 
PROCEDURE TraceDescriptionVariable(DescVar,_iProfondeur est un entier,LOCAL oObj=Null)
 
sProfondeur est une chaîne
sProfondeur = Complète("",_iProfondeur*5)
 
Trace(sProfondeur+"--------------------")
Trace(sProfondeur+"Variable : "+DescVar..Nom+" | Global : "+DescVar..Global+" | Hérité : "+DescVar..Hérité+" | Masquage : "+DescVar..Masquage)
 
Def est une Définition
 
SI oObj <> Null ALORS 
	SELON DescVar..Définition..Type
 
		CAS 34//Tableau
 
			SI {oObj,DescVar}..Occurrence > 0 ALORS
				Def = RécupèreDéfinition({oObj,DescVar}[1])                              
				SI Def = Null ALORS
					Erreur(ErreurInfo(errComplet))
					RENVOYER Faux
				FIN
				POUR i = 1 _A_ {oObj,DescVar}..Occurrence
					SELON Def..Type
						CAS 36,37//Objet ou Structure
							Trace(sProfondeur+"Valeur "+DescVar..Nom+"["+i+"] : ")
							TraceDefinition(Def,_iProfondeur,{oObj,DescVar}[i])
						AUTRE CAS
							Trace(sProfondeur+"Valeur "+DescVar..Nom+"["+i+"] : "+{oObj,DescVar}[i])
					FIN
				FIN
			FIN
 
		CAS 62//Tableau associatif
 
			SI {oObj,DescVar}..Occurrence > 0 ALORS
				POUR TOUT vValeur, vCle de {oObj,DescVar}
					Def = RécupèreDéfinition(vValeur)                              
					SI Def = Null ALORS
						Erreur(ErreurInfo(errComplet))
						RENVOYER Faux
					FIN
					SELON Def..Type
						CAS 36,37//Objet ou Structure
							Trace(sProfondeur+"Valeur "+DescVar..Nom+"["+vCle+"] : ")
							TraceDefinition(Def,_iProfondeur,{oObj,DescVar}[vCle])
						AUTRE CAS
							Trace(sProfondeur+"Valeur "+DescVar..Nom+"["+vCle+"] : "+{oObj,DescVar}[vCle])
					FIN
				FIN
			FIN	
 
		CAS 36,37//Objet ou Structure
 
			Def = RécupèreDéfinition({oObj,DescVar})                              
			SI Def = Null ALORS
				Erreur(ErreurInfo(errComplet))
				RENVOYER Faux
			FIN
			TraceDefinition(Def,_iProfondeur,{oObj,DescVar})
 
		AUTRE CAS//Type primitif
 
			TraceDefinition(DescVar..Définition,_iProfondeur,oObj)
			Trace(sProfondeur+"Valeur : "+{oObj,DescVar})
	FIN
FIN
 
RENVOYER Vrai
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
 
PROCEDURE TraceDescriptionProcédure(DescProc,_iProfondeur est un entier)
 
sProfondeur est une chaîne
sProfondeur = Complète("",_iProfondeur*5)
 
Trace(sProfondeur+"--------------------")
Trace(sProfondeur+"Procédure Nom : "+DescProc..Nom+" | Global : "+DescProc..Global+" | Hérité : "+DescProc..Hérité+" | Virtuel : "+DescProc..Virtuel)
//Trace("Déclaration :")
//TraceDefinition(DescProc..Déclaration)
Et pour finir, voici la procédure de comparaison des valeurs des membres de deux instances d'une même classe (les différences constatées apparaissent dans une fenêtre de trace) :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
 
PROCEDURE ComparerObjets(_oObj1,_oObj2)
 
Def est une Définition
Def = RécupèreDéfinition(_oObj1)                              
SI Def = Null ALORS
	Erreur(ErreurInfo(errComplet))
	RENVOYER Faux
FIN
 
ParcoursVariables(Def,_oObj1,_oObj2)
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
 
PROCEDURE ParcoursVariables(LOCAL _Def est une Définition,LOCAL oObj1=Null,LOCAL oObj2=Null,sParentNom est une chaîne="")
 
Def est une Définition
 
POUR TOUT DescVar DE _Def..Variable
 
	SI oObj1 <> Null ALORS 
		SELON DescVar..Définition..Type
 
			CAS 34//Tableau
 
				SI {oObj1,DescVar}..Occurrence <> {oObj2,DescVar}..Occurrence ALORS
					Trace("-----------------------------")
					Trace("Différence détectée variable "+sParentNom+":"+DescVar..Nom)
					Trace("Obj1 Nb occurences : "+{oObj1,DescVar}..Occurrence)
					Trace("Obj2 Nb occurences : "+{oObj2,DescVar}..Occurrence)
				SINON
					SI {oObj1,DescVar}..Occurrence > 0 ALORS
						Def = RécupèreDéfinition({oObj1,DescVar}[1])                              
						SI Def = Null ALORS
							Erreur(ErreurInfo(errComplet))
							RENVOYER Faux
						FIN
						POUR i = 1 _A_ {oObj1,DescVar}..Occurrence
							SELON Def..Type
								CAS 36,37//Objet ou Structure
									ParcoursVariables(Def,{oObj1,DescVar}[i],{oObj2,DescVar}[i],sParentNom+":"+DescVar..Nom+"["+i+"]")
								AUTRE CAS
									SI {oObj1,DescVar}[i] <> {oObj2,DescVar}[i] ALORS
										Trace("-----------------------------")
										Trace("Différence détectée variable "+sParentNom+":"+DescVar..Nom+"["+i+"]")
										Trace("Obj1 Valeur : "+{oObj1,DescVar}[i])
										Trace("Obj2 Valeur : "+{oObj2,DescVar}[i])
									FIN
							FIN
						FIN
					FIN
				FIN
 
			CAS 62//Tableau associatif
 
				SI {oObj1,DescVar}..Occurrence > 0 ALORS
					POUR TOUT vValeur, vCle de {oObj1,DescVar}
						Def = RécupèreDéfinition(vValeur)                              
						SI Def = Null ALORS
							Erreur(ErreurInfo(errComplet))
							RENVOYER Faux
						FIN
						SELON Def..Type
							CAS 36,37//Objet ou Structure
								SI {oObj2,DescVar}[vCle] = Null ALORS
									Trace("-----------------------------")
									Trace("Différence détectée variable "+sParentNom+":"+DescVar..Nom+"["+vCle+"]")
									Trace("Obj1 Valeur : "+Def..Nom)
									Trace("Obj2 Valeur : NULL")
								SINON
									ParcoursVariables(Def,{oObj1,DescVar}[vCle],{oObj2,DescVar}[vCle],sParentNom+":"+DescVar..Nom+"["+vCle+"]")
								FIN
							AUTRE CAS
								SI {oObj1,DescVar}[vCle] <> {oObj2,DescVar}[vCle] ALORS
									Trace("-----------------------------")
									Trace("Différence détectée variable "+sParentNom+":"+DescVar..Nom+"["+vCle+"]")
									Trace("Obj1 Valeur : "+{oObj1,DescVar}[vCle])
									Trace("Obj2 Valeur : "+{oObj2,DescVar}[vCle])
								FIN
						FIN
					FIN
				FIN
 
			CAS 36,37//Objet ou Structure
 
				Def = RécupèreDéfinition({oObj1,DescVar})                              
				SI Def = Null ALORS
					Erreur(ErreurInfo(errComplet))
					RENVOYER Faux
				FIN
				ParcoursVariables(Def,{oObj1,DescVar},{oObj2,DescVar},sParentNom+":"+DescVar..Nom)
 
			AUTRE CAS//Type primitif
 
				SI {oObj1,DescVar} <> {oObj2,DescVar} ALORS
					Trace("-----------------------------")
					Trace("Différence détectée variable "+sParentNom+":"+DescVar..Nom)
					Trace("Obj1 Valeur : "+{oObj1,DescVar})
					Trace("Obj2 Valeur : "+{oObj2,DescVar})
				FIN	
 
		FIN
 
	FIN
 
FIN
Bonne prog