IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

QxOrm Discussion :

Question sur l'introspection


Sujet :

QxOrm

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Saône (Franche Comté)

    Informations forums :
    Inscription : Août 2011
    Messages : 26
    Par défaut Question sur l'introspection
    Bonjour, encore moi

    J'ai besoin d'instancier une classe persistante dont je ne connais le type qu'à l'exécution... pas de soucis avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::any o = qx::create(...);
    Maintenant, je souhaite définir les propriétés de "o", mais toujours en faisant abstraction du type de la classe persistante. Dans le tuto de QxBlog, il y a cet exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
       // Création d'un 'blog' à partir du nom de la classe (design pattern 'factory')
       boost::any blog_any = qx::create("blog");
       blog_ptr blog_1 = boost::any_cast<blog_ptr>(blog_any);
       blog_1->m_text = "blog_text_1";
       blog_1->m_dt_creation = QDateTime::currentDateTime();
       blog_1->m_author = author_1;
    mais ça implique un "cast"...

    Est il possible de faire un "setProperty("...", value)" sur un objet créé par qx::create sans en connaitre le type à la compilation ?

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    482
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 482
    Par défaut


    mais ça implique un "cast"...
    Est il possible de faire un "setProperty("...", value)" sur un objet créé par qx::create sans en connaitre le type à la compilation ?
    Oui c'est possible, voici 2 solutions à ton problème :

    1- Est-ce que tu as une classe de base commune à toutes tes classes persistantes (QObject par exemple) ?
    Si oui, pas de problème, tu peux "caster" avec la classe de base puis utiliser le moteur d’introspection pour valoriser les propriétés.
    Voici un exemple avec une classe persistante ayant QObject comme classe de base, on valorise à 3 la propriété my_property de la classe MyQObject :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef boost::shared_ptr<QObject> QObject_ptr;
    boost::any any_object = qx::create("MyQObject");
    QObject_ptr my_object = boost::any_cast<QObject_ptr>(any_object);
    qx::IxDataMember pData = qx::QxClassX::getDataMember("MyQObject", "my_property");
    if (pData) { pData->setValue<int>(my_object.get(), 3); }
    2- Si tu ne veux pas utiliser boost::any et boost::shared_ptr, il y a plus simple. Au lieu d'utiliser qx::create(...), tu peux utiliser qx::create_nude_ptr(...). Attention, ça crée un pointeur nu et ce sera à ton code de détruire l'instance (en faisant un delete).
    Voici le même exemple que ci-dessus avec la classe MyObject qui ne dérive pas de QObject cette fois-ci (imaginons qu'elle n'a aucune classe de base, on passe alors par void *) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void * pObject = qx::create_nude_ptr<void>("MyObject");
    qx::IxDataMember pData = qx::QxClassX::getDataMember("MyObject", "my_property");
    if (pData) { pData->setValue<int>(pObject, 3); }
    Remarque : au lieu de setValue, tu peux aussi utiliser la méthode suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pData->fromVariant(pObject, 3);
    Le site de la bibliothèque QxOrm : bibliothèque C++ de gestion de données (Mapping Objet Relationnel ou ORM) basée sur les frameworks Qt et boost.
    QxEntityEditor : éditeur graphique pour la bibliothèque QxOrm (application multi-plateforme pour gérer graphiquement le modèle d'entités).

    Tutoriel : installer un environnement de développement avec QxOrm sous Windows.
    Tutoriel qxBlog : gestion de blogs en C++/Qt.
    Tutoriel qxClientServer : création d'un serveur d'applications en C++/Qt.

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Saône (Franche Comté)

    Informations forums :
    Inscription : Août 2011
    Messages : 26
    Par défaut


    Super, exactement ce qu'il me fallait !

    Juste une dernière question, est-ce l'on peut appeler qx::dao::save(pObject);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
                void * pObject = qx::create_nude_ptr<void>("MyObject");
                qx::IxDataMember pData = qx::QxClassX::getDataMember("MyObject", "my_property");
                if (pData) { pData->setValue<int>(pObject, 3); }
                qx::dao::save(pObject);
    vu que pObject est un void*
    pour ta disponibilité.

  4. #4
    Membre Expert

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    482
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 482
    Par défaut
    Désolé, je viens de tester et aucune des 2 solutions proposées dans mon message précédent ne fonctionne , mais l'idée était là
    - la 1ère solution ne marche pas car boost::any ne supporte pas le polymorphisme (et donc encore moins le polymorphisme de pointeurs intelligents).
    - la 2ème solution fonctionne uniquement si tu as une classe de base commune pour toutes tes classes persistantes. Si tu utilises void *, tu auras une erreur de compilation à cause d'un dynamic_cast. La correction à apporter n'est pas trop complexe, je le ferai dans la prochaine version de QxOrm...

    Voici ce que tu peux faire facilement en attendant la prochaine version de QxOrm : dans le fichier './include/QxFactory/QxFactoryX.h', rend public la méthode 'static inline void * createInstanceNudePtr(const QString & sKey)' qui est actuellement private.
    Du coup, le code de la 2ème solution devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void * pObject = qx::QxFactoryX::createInstanceNudePtr("MyObject");
    qx::IxDataMember pData = qx::QxClassX::getDataMember("MyObject", "my_property");
    if (pData) { pData->setValue<int>(pObject, 3); }
    Juste une dernière question, est-ce l'on peut appeler qx::dao::save(pObject);
    Non, il faut connaitre le type de pObject pour appeler les fonctions qx::dao::....

    Si tu veux implémenter un tel mécanisme, voici ce qui me semble le plus propre pour la conception :
    - tu crées une interface (ou plutôt une classe abstraite en C++), du style IxPersistable, avec les méthodes virtuelles pures suivantes : fetch, update, insert, delete, save, etc...
    - toutes tes classes persistantes doivent implémenter l'interface IxPersistable.
    - ensuite tu utilises qx::create_nude_ptr<IxPersistable>(...) pour créer une instance d'un type persistant.
    - à partir de là tu peux appeler la méthode save() par exemple.

    Voilà ça fait beaucoup de boulot mais c'est ce qui me semble le plus propre.
    Après faut voir avec ton besoin réel.
    Dans quel contexte tu veux mettre un tel mécanisme en place ?
    Le site de la bibliothèque QxOrm : bibliothèque C++ de gestion de données (Mapping Objet Relationnel ou ORM) basée sur les frameworks Qt et boost.
    QxEntityEditor : éditeur graphique pour la bibliothèque QxOrm (application multi-plateforme pour gérer graphiquement le modèle d'entités).

    Tutoriel : installer un environnement de développement avec QxOrm sous Windows.
    Tutoriel qxBlog : gestion de blogs en C++/Qt.
    Tutoriel qxClientServer : création d'un serveur d'applications en C++/Qt.

  5. #5
    Membre averti
    Homme Profil pro
    Inscrit en
    Août 2011
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Saône (Franche Comté)

    Informations forums :
    Inscription : Août 2011
    Messages : 26
    Par défaut
    Je souhaite que mon prog puisse importer la BD TOPO de l'IGN en db.

    Pour cela, je parse les fichiers shapefile (une trentaine au moins) et à chacun correspond une table (avec des champs différents).

    La routine d'import étant toujours la même, je souhaitais développer une routine générique qui, en fonction du shapefile, créé une instance de la classe persistante correspondante, la renseigne avec les propriétés du shapefile, puis la sauve en db.

    Les noms des champs de chaque table étant identiques aux champs des shapefiles correspondants, l'introspection me semblait être la solution.

    Toutefois, dans ce cas précis, je peux créer les requêtes "INSERT INTO ..." manuellement, et donc maîtriser complètement le nom des tables et des champs, en m'appuyant sur qx::QxClassX, etc...

    PS : j'ai utilisé la solution N°2 en utilisant QObject à la place de void. (sans modifier QxOrm)

    Ça fonctionne, mais ne règle pas le problème qx::dao::save(...)

    C'est d'ailleurs à ça que les "repository" pourraient servir '
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    repository<MonType>::save(MonObjet)

  6. #6
    Membre Expert

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    482
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 482
    Par défaut
    PS : j'ai utilisé la solution N°2 en utilisant QObject à la place de void. (sans modifier QxOrm)
    Oui si toutes tes classes persistantes dérivent de QObject, alors le code suivant fonctionne sans problème avec la version courante de QxOrm (c'est ce qui est utilisé par exemple avec le module QxService, en remplaçant QObject par qx::IxService) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    QObject * pObject = qx::create_nude_ptr<QObject>("MyQObject");
    qx::IxDataMember pData = qx::QxClassX::getDataMember("MyQObject", "my_property");
    pData->setValue<int>(pObject, 3);

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    C'est d'ailleurs à ça que les "repository" pourraient servir ' :
    repository<MonType>::save(MonObjet)
    Je ne vois pas trop comment le code ci-dessus avec le repository pourrait résoudre ton problème : quand tu écris repository<MonType>, tu dois spécifier MonType, de la même façon que qx::dao::save<MonType>(...).
    Je pense que l'intérêt d'un repository est d'avoir une interface commune pour effectuer les actions de persistance (fetch, insert, update, delete, etc.). Dans ton cas, il faudrait y accéder par le nom de la classe "MonType", au lieu du template <MonType>.

    Donc je pense qu'un code comme ça pourrait résoudre ta problématique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    qx::IxRepository * pRepository = qx::QxRepositoryX::get("MonType");
    pRepository->save(MonObjet);
    T'en penses quoi ?

    Ce n'est pas très complexe à mettre en place dans la bibliothèque QxOrm, je le ferai dans la prochaine version...
    Par contre, j'ai un peu peur que ça rallonge fortement les temps de compilation des classes persistantes, donc je mettrai peut-être une option de compilation pour accéder au repository par introspection (si je vois pendant mes tests que ça dégrade trop la compil).
    L'accès au repository par template sera toujours accessible (peu importe l'option de compilation s'il il y en a une), mais par nom de classe (l'exemple ci-dessus) on verra...
    Sinon, l'interface qx::IxRepository aura des méthodes avec pour paramètres void * (certains diront BEURK mais je pense que c'est mieux que boost::any puisqu'il ne gère pas le polymorphisme, on fera des dynamic_cast pour vérifier l'instance passée en paramètre...).
    Le site de la bibliothèque QxOrm : bibliothèque C++ de gestion de données (Mapping Objet Relationnel ou ORM) basée sur les frameworks Qt et boost.
    QxEntityEditor : éditeur graphique pour la bibliothèque QxOrm (application multi-plateforme pour gérer graphiquement le modèle d'entités).

    Tutoriel : installer un environnement de développement avec QxOrm sous Windows.
    Tutoriel qxBlog : gestion de blogs en C++/Qt.
    Tutoriel qxClientServer : création d'un serveur d'applications en C++/Qt.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [debutant] Questions sur 1 futur projet
    Par cyrull22 dans le forum XML/XSL et SOAP
    Réponses: 3
    Dernier message: 28/04/2003, 21h49
  2. Quelques questions sur le TWebBrowser...
    Par CorO dans le forum Web & réseau
    Réponses: 3
    Dernier message: 17/01/2003, 21h23
  3. Question sur les handles et les couleurs...
    Par MrDuChnok dans le forum C++Builder
    Réponses: 7
    Dernier message: 29/10/2002, 08h45
  4. Réponses: 2
    Dernier message: 11/08/2002, 21h27
  5. question sur les message box !
    Par krown dans le forum Langage
    Réponses: 7
    Dernier message: 02/08/2002, 16h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo