Obtenir les objets (instances)

ricklekebekoi Messages postés 303 Date d'inscription mardi 11 février 2003 Statut Membre Dernière intervention 24 avril 2009 - 2 mai 2008 à 22:03
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 - 22 juil. 2008 à 11:51
Bonjour,

J'ai un besoin crucial de savoir toutes les instances existante d'une classe précise et de ces sous-classes.
J'ai tout d'abord pensé a faire une liste, mais ça implique d'appeler explicitement le destructeur car sinon elle reste a jamais dans cette liste.

Bref, par reflexion ou tout autre procédé, existe-t-il un moyen de savoir les instance d'une classe précise a un moment précis de l'execution ? Sinon qu'elle solution me proposez vous pour bien gérer le tout ?

Le probleme est que le but de ce developpement sera d'en produire une dll, donc obliger les utilisateurs de la dll a appeler explicitement une fonction pour enlever l'objet de la liste me déplait, donc j'essai de trouver mieux !

Eric

12 réponses

cs_coq Messages postés 6349 Date d'inscription samedi 1 juin 2002 Statut Membre Dernière intervention 2 août 2014 101
3 mai 2008 à 00:19
Salut,

Je ne crois pas que de tels mécanismes de parcours du heap dans le programme en lui même soit fournis de base.
Quel est le besoin nécessitant la mise en place d'une telle machinerie ?

/*
coq
MVP Visual C#
CoqBlog
*/
0
ricklekebekoi Messages postés 303 Date d'inscription mardi 11 février 2003 Statut Membre Dernière intervention 24 avril 2009 5
3 mai 2008 à 01:05
En fait, c'est pour simplifier la sauvegarde dans un fichier a l'aide de la serialization.

Les éléments héritent donc tous d'un type de base (UniqueObject) qui lui contient la propriété "Serial" qui est en soi un numéro d'identification unique, et 2 méthodes "Serlialize()" et "Deserialize()"

Ainsi, lors de la save, prenons par exemple un verger, il contient 500 pommes ayant tous en propriété "Parent" l'un des 10 arbres duquel il provient. Lors de l'enregistrement, je veut qu'il sauvegarde 500 pomes et 10 arbres, et non 500 pommes et 500 arbres.

Du coup, je n'enregistre pour la pomme que le numero de serial auquel il est associé, et j'enregistre ensuite de maniere unique chacuns des objets.

Afin que ça fonctionne bien, j'ai besoin de savoir les objets unique actuellement alloués pour enregistrer leur contenu.

Eric
0
ricklekebekoi Messages postés 303 Date d'inscription mardi 11 février 2003 Statut Membre Dernière intervention 24 avril 2009 5
3 mai 2008 à 01:14
En fait le probleme que j'ai, c'est que je doit enregistrer la liste des objets unique avant d'aller enregistrer leur contenu, car sinon deserializer la pomme avant l'arbre serait fatal. Pire encore, si mon arbre contient une props "PommeMagique" qui fait référence a l'une de ces pommes, eh bah je serais dans l'embaras peu importe lequel des 2 je deserialize en premier.

Eric
0
cs_coq Messages postés 6349 Date d'inscription samedi 1 juin 2002 Statut Membre Dernière intervention 2 août 2014 101
3 mai 2008 à 11:58
Heu mettre en oeuvre des mécanismes aussi lourds que des parcours du heap pour faire ça me parrait suicidaire.
Tu peux en revanche t'orienter vers des solutions de type fabrique, où tu ne laisses pas la possibilité à l'utilisateur de créer les instances directement mais uniquement via une méthode Create, te permettant ainsi de mettre en place des mécanisme de mémorisation des instances crées.

/*
coq
MVP Visual C#
CoqBlog
*/
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
ricklekebekoi Messages postés 303 Date d'inscription mardi 11 février 2003 Statut Membre Dernière intervention 24 avril 2009 5
3 mai 2008 à 17:53
Oui le parcours du heap c'est effectivement pas je croit la meilleur idée.
En fait mon probleme n'est pas de les "noter" lors de l'assignation, mais plutot de les enlever lorsqu'ils ne servent plus

Eric
0
ricklekebekoi Messages postés 303 Date d'inscription mardi 11 février 2003 Statut Membre Dernière intervention 24 avril 2009 5
3 mai 2008 à 17:56
La solution qui me vient en tete serait de noter lors du deserialize ceux qui ne sont pas appelés et de les enlevés, mais si l'arbre a eu 1000 pommes durant l'execution et qu'il n'en reste que 3, yen aura quand meme 1000 dans la save, mais que 3 après reboot. Donc j'aimerais trouver mieux :)

Eric
0
jesusonline Messages postés 6814 Date d'inscription dimanche 15 décembre 2002 Statut Membre Dernière intervention 13 octobre 2010 29
3 mai 2008 à 18:24
Bonjour,
je ne comprend pas ce que tu cherches à faire (ce que je comprend c'est que tu cherches à faire un complexifier un truc d'apparence simple).
En tout cas les mots que j'ai capté me font penser aux WeakReference (http://msdn.microsoft.com/en-us/library/system.weakreference.aspx) qui te permettront d'avoir un lien faible (non pris en compte par le GC) sur l'instance d'un objet. C'est juste une piste, je ne vois pas en quoi ca peut servir puisque je comprend pas trop la problèmatique ;)

<hr />Cyril - MSP - MCPD ASP.net & MCTS SQL - Consultant indépendant
0
ricklekebekoi Messages postés 303 Date d'inscription mardi 11 février 2003 Statut Membre Dernière intervention 24 avril 2009 5
4 mai 2008 à 17:29
J'ai jeter un oeil et malheureusement je ne croit pas que ce soit la solution idéale
"Tu cherches a complexifier un truc d'apparence simple"
C'est possible, je n'ai probablement pas la bonne approche is c'est le cas.

Mon objectif:
Présenter un système de Save/Load utilisant la serialisation binaire et l'utiliser de manière efficace même lorsque les objets à serializer sont complexes. Permettre a l'usager d'avoir a n'en faire le moins possible pour enregistrer ces trucs dans un fichier et les reloader.

Ma solution, lors du Save:
Faire heriter les objets à sauvegarder d'un objet contenant un "Serial", soit un numéro unique associé a l'objet. N'enregistrer tout d'abord dans le fichier la liste des serial à enregistrer, puis ensuite Serialiser chacun des objets associé.

Ma solution, lors du Load:
Créer des objets vides avec chacun des serials de la liste. Leur propriétés se rempliront lorsque le deserialize de cet objet sera appelé. Deserializer ensuite chacun des objets de la liste.

Exemple:
Dans mon programme de gestion familial, j'ai 5 objets de type personne:
Personne( string nom, DateTime dateNaiss, Personne[] Amis )
Serial 0x45CF : Personne( Bob, 1987-01-09, {Ginette,Alphonse})
Serial 0x55E3 : Personne( Ginette, 1988-03-13, {Bob,Leo} )
Serial 0x1CF8: Personne( Leo, 1989-05-14, {Ginette,Alphonse,Rita} )
Serial 0x432E : Personne( Alphonse, 1980-07-21, {Bob,Leo,Rita} )
Serial 0x1111 : Personne( Rita, 1981-08-31, {Leo,Alphonse} )

Au moment de la save, je save d'abord type&serial
0x45CF : Personne
0x55E3 : Personne
0x1CF8: Personne
0x432E : Personne
0x1111 : Personne

Ensuite, je serialize chacun des objets. Lorsqu'un objet de type Personne est demandé, il n'écrit que le serial de la personne
Personne : 0x45CF, Bob, 1987-01-09, 2, 0x55E3, 0x432E
Personne : 0x55E3, Ginette, 1988-03-13, 2, 0x45CF, 0x1CF8
Personne : 0x1CF8, Leo, 1989-05-14, 3, 0x55E3, 0x432E, 0x1111
Personne : 0x432E, Alphonse, 1980-07-21, 3, 0x45CF, 0x1CF8, 0x1111
Personne : 0x1111, Rita, 1981-08-31, 2, 0x432E, 0x1CF8

Voila, ils ont tous été sauvegardés de manière unique.
Maintenant, si l'on desire loader le tout, on va commencer par créer les 5 objets personnes en n'y déposant QUE le serial.
new Personne(0x45CF );
new Personne(0x55E3 );
new Personne(0x1CF8 );
new Personne(0x432E );
new Personne(0x1111 );

Ensuite, on appel la fonction deserialize des objets. Au moment de déserializer le premier, 0x45CF, il fait référence aux 2 objets 0x55E3, 0x432E. Puisque 2 objets existe avec ces 2 serial, on peut directement les référencés sans problemes et ce même si ces objets ne sont pas encore deserializé.

Au final, nous nous retrouvons avec la même structure qu'au départ, et la save aura nécessité un minimum d'espace memoire.

Probleme rencontré:

Dans cet histoire, Bob part en voyage loin loin, mais son avion Crash, et meurt.
On enleve donc Bob des amis de Ginette et Alphonse, car Bob n'existe plus dans le systeme.
Au moment de la save, on enregistrera toujours bob, car même si celui-ci n'existe plus dans le système, il est encore dans la liste des "ObjetsUnique" A sauvegarder.

Solutions trouvés:

1. Obliger l'usager a appeler explicitement une methode "Dispose()" ou similaire qui permetterait de l'enlever de la liste et de "nullifier" l'objet. Cette action me déplait car il faudra obliger l'usager a le faire lui meme toujours. Dans le cas de l'Exemple, c'est simple rajouter la ligne dans la fonction "Meurt()" de Personne. Parcontre, dans des systemes plus complexes ou tres différentes, ce ne sera pas commode.

2. Lors du load, noter tous les objets encore utilisés et ceux qui ne le sont plus. Supprimer les inactif et lors de la prochaine save, elle aura ceux-la en moins. Cette solution me déplait car la save sera parfois tres volumineuse pour rien sur le disque, et le Load() sera fait de maniere plus lente.

3. Lors du save, effectuer une premiere fois la save dans un fichier bidon, pour noter les objets utilisés. Ensuite enlever les inactifs et faire la vrai save. Cette solution me déplait car la save sera énormément longue dans les gros systemes.

Conclusion:
Bref, la solution 2 serait celle que j'implémenterais je pense faute d'avoir une meilleure solution, tout en ajoutant la solution 1 en "a coté" a l'usagé. Maius bon, j'aimerais trouver mieux.
Donc, est-ce que je complexifie quelquechose de simple et que je pourrais obtenir un resultat semblable de maniere bien plus intéressante et simple ?
Et si non, comment pourrais-je miraculeusement résoudre mon problème ?

Un gros merci, j'espere qu'avec ce roman tout est plus clair

Eric
0
ricklekebekoi Messages postés 303 Date d'inscription mardi 11 février 2003 Statut Membre Dernière intervention 24 avril 2009 5
7 mai 2008 à 20:44
Auncune idée personne ???

Eric
0
jesusonline Messages postés 6814 Date d'inscription dimanche 15 décembre 2002 Statut Membre Dernière intervention 13 octobre 2010 29
7 mai 2008 à 23:17
J'ai pas encore eu le temps de lire ta réponse ! Mais c'est dans ma todo :) Je ne serais pas étonné que l'ami coq te réponde avant moi :p 

<hr />Cyril - MSP - MCPD ASP.net & MCTS SQL - Consultant indépendant
0
cs_coq Messages postés 6349 Date d'inscription samedi 1 juin 2002 Statut Membre Dernière intervention 2 août 2014 101
8 mai 2008 à 19:02
Moi aussi j'étais un peu à court de temps :s

Logiquement le BinaryFormatter fait déjà ce travail.

Mais pour faire ce que tu veux je pense que tu as pris le problème dans le mauvais sens : ce que tu veux faire est simplement ne pas sérialiser 2 fois la même chose, la même chose étant identifiée ici par la référence à l'objet : tu n'as pas besoin d'avoir la liste complète des instances de Personne ayant été crées au début du processus, mais plutôt la liste de celles que tu as déjà sérialisées, liste que tu batis au fur et à mesure de la persistance.

Enfin, ce n'est qu'une piste supplémentaire, je ne sais pas si d'autre points bloquant l'accompagnent, suivant la fonctionnement de ton moteur en général.

/*
coq
MVP Visual C#
CoqBlog
*/
0
ShareVB Messages postés 2676 Date d'inscription vendredi 28 juin 2002 Statut Membre Dernière intervention 13 janvier 2016 26
22 juil. 2008 à 11:51
salut,

tu peux utiliser IXmlSerializable pour faire ta sérialisation à la main et ainsi savoir quand une instance a été sérialisée...mais bon...je ne sais pas si c'est le plus simple car il faut faire du XmlReader et XmlWriter à la main pour sérialiser....

ShareVB
0
Rejoignez-nous