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

C# Discussion :

recomposition d'un objet à partir d'une carte


Sujet :

C#

  1. #1
    Membre régulier
    Profil pro
    Développeur Web
    Inscrit en
    Décembre 2004
    Messages
    97
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2004
    Messages : 97
    Points : 89
    Points
    89
    Par défaut recomposition d'un objet à partir d'une carte
    Bonjour,

    je vais essayé d'exposer mon problème le plus clairement possible...

    J'ai une classe User, une classe DataObject et dans une base de données une table Users.
    - La classe User étend la classe DataObject.
    - La classe DataObject possède, entre autre, une propriété fieldsmap.
    - Les propriétés de ma classe User correspondent aux champs de ma table Users.
    - Dans ma classe User, j'initialise la propriété fieldsmap ; qui est en fait un tableau associatif qui représente une carte de la table Users
    - Ma classe DataObject possède plusieurs méthodes dont une méthode findAll(...) qui me renvoie un tableau d'objets.

    Ce que je cherche à faire :
    Je souhaiterais que lorsque j'appelle la méthode findAll(...) ma classe DataObject renvoie un tableau d'objet de type User qu'elle aurait recomposé grâce à la carte fieldsMap.
    En gros, j'essaie de faire en sorte que la classe DataObject soit capable de construire un objet par rapport à la carte fieldsMap
    Tout est clair dans ma tête, je câle niveau syntaxe et technique.

    On parvient à le faire en php, ça doit certainement être possible mais comment ...

    Ce qui est décrit ci-dessus inteviendra dans un projet asp.net

    merci,

    Excellente soirée,

    Philippe

    PS : ...Petite précision, je fais essentiellement du php et de l'asp classique , je débute en .net

  2. #2
    Rédacteur

    Avatar de Jérôme Lambert
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2003
    Messages
    4 451
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 451
    Points : 14 357
    Points
    14 357
    Par défaut
    J'aime bien ce genre de question

    Pour y arriver, il faudra :
    • Une bonne dose de Réflexion (System.Reflection);
    • Un soupçon de notion d'héritage;
    • Et une pincée de logique;
    Donc, je reprend tes explications avec un petit exemple :

    Une table table_User dans la base de données :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Champs 
    field_id int
    field_nom varchar(50)
    Une classe DataObject :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public abstract class DataObject
    {
    private string m_tablename = string.Empty;
     
    public DataObject(string tb_name)
    { this.m_tablename = tb_name; }
     
    public abstract Dictionnary<string, string> fieldsmap();
    }
    Une classe User qui hérite de la classe DataObject et qui va donc implémenter la méthode fieldsmap :

    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
    public class User : DataObject
    {
    private int m_Id = 0;
    private string m_Nom = string.Empty;
     
    public User(string tb_name) : base(tb_name)
    { }
     
    public override Dictionnary<string, string> fieldsmap()
    {
    // La clé est le nom du champ
    // La valeur est le nom de la propriété correspondante dans l'objet courant
    Dictionnary<string, string> objFieldsMap = new Dictionary<string, string>();
     
    objFieldsMap.Add("field_id", "Id");
    objFieldsMap.Add("field_nom", "Nom");
     
    return objFieldsMap;
    }
     
    public int Id
    {
    get{ return m_Id; }
    set{ m_Id = value; }
    }
     
    public string Nom
    {
    get{ return m_Nom; }
    set{ m_Nom = value; }
    }
    }
    Maintenant, il reste à écrire cette fameuse méthode FindAll qui va récupérer la liste des tuples dans table_User et qui vont être transformés en objets User. Où va-t-on écrire ce code ? Dans DataObject évidemment pour en faire une méthode "générique". Je suppose que tu exécute ta requête avec un DataReader, je ne vais donc détailler ici que le code parcourant chaque row renvoyée par le DataReader :

    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
    public List<User> FindAll()
    {
    Dictionary<string, string> objFieldsMap = this.fieldsMap();
     
    // Création de la query, tu peux te servir du dictionnaire renvoyé par fieldsmap pour construitre la méthode select de manière dynamique
     
    // Ta requête est exécutée et on se retrouve avec objDataReader prêt à être parcouru :
     
    // Cet objet list va contenir tous les objets User
    List<User> objUsers = new List<User>;
    while(objDataReader.Read())
    {
    // On va tout d'abord créer une instance de l'objet courant, dans notre cas, ce sera User
    DataObject objObjectToFill = Activator.CreateInstance(this.GetType()) as DataObject;
     
    // On est sur la ligne courante, on va donc récupérer chaque valeur grâce à objFieldsMap
    foreach(string fieldname in objFieldsMap.Values)
    {
    object value = objDataReader[fieldname];
     
    // Maintenant, on va remplir la bonne propriété de l'objet objObjectToFill grâce à la réflexion
    System.Reflection.PropertyInfo objPropertyInfo = this.GetType().GetProperty(objFieldsMap[fieldName]);
    objPropertyInfo.SetValue(objObjectToFill, value, null);
    }
     
    // Une fois que l'objet est rempli, il reste plus qu'à l'ajouter à la liste
    objUsers.Add(objObjectToFill);
    }
     
    // Quand on a parcouru toutes les rows (on oublie pas de fermer l'objet command :p)
    // Et on renvoie l'objet list
    return objUsers;
    }
    Voilà, je ne peux pas te garantir que ça va fonctionner comme ça car j'ai écrit ça sans le tester mais tu as le principe.

    Si tu as quelques soucis de compréhension avec certains points, n'hésite pas, je me doute que ça ne doit pas être facile de passer de php/asp à asp.net.

  3. #3
    Membre régulier
    Profil pro
    Développeur Web
    Inscrit en
    Décembre 2004
    Messages
    97
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2004
    Messages : 97
    Points : 89
    Points
    89
    Par défaut
    Bonjour,

    Déjà ! un grand merci, Cardi, pour ces infos et exemples ! Ca éclaircit déjà beaucoup mes pensées !

    La réflexion : je suis justement tombé hier soir sur ce post [VS2005][C#] Création et recherche dynamique d'objet

    Il y a encore un point qui m'inquiète :

    Le but de ma classe DataObject, c'est que plusieurs type d'objet pourront l'étendre (une classe User, une classe Company, une classe News, ...), si je prends par exemple la fonction List<User> FindAll()
    Comment lui spécifier le type d'objet (User ? Company ? News ?) qu'elle va devoir me rendre ? Je suppose que c'est ici que va intervenir, entre autre, la réflexion ?

    Bon appétit,

    Phil-

  4. #4
    Rédacteur

    Avatar de Jérôme Lambert
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2003
    Messages
    4 451
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 451
    Points : 14 357
    Points
    14 357
    Par défaut
    Citation Envoyé par Philoulheinz Voir le message
    Le but de ma classe DataObject, c'est que plusieurs type d'objet pourront l'étendre (une classe User, une classe Company, une classe News, ...), si je prends par exemple la fonction List<User> FindAll()
    Comment lui spécifier le type d'objet (User ? Company ? News ?) qu'elle va devoir me rendre ? Je suppose que c'est ici que va intervenir, entre autre, la réflexion ?

    Oui tout à fait, grâce à la réflexion, on va pouvoir créer tout simplement une instance du type courant.

    Tout d'abord, il faut savoir qu'avec la réflexion, on joue beaucoup avec la classe Type qui est le "coeur" de la réflexion dans le sens que c'est grâce à cette classe abstraite qu'on va pouvoir accéder aux métadonnées d'une classe donnée.

    Pour ce faire, tout les types du framework ainsi que ceux que tu vas créer à l'avenir proposent la méthode GetType() pour récupérer une instance Type de l'objet en question.


    En écrivant ceci à l'intérieur de la classe, tu vas pouvoir récupérer l'objet Type correspondant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Type monType = this.GetType();
    Si tu as écrit ceci dans :
    • La classe User, tu auras les informations de la classe User;
    • La classe Company, tu auras les informations de la classe Company;
    • La classe DataObject, tu auras les informations de la classe qui hérite de DataObject (vive l'héritage);
    Voila, tu as ton instance de Type qui te donne les informations de la classe courante mais c'est tout. Toi il te faut une instance de User, Company, ... C'est ici qu'intervient la classe Activator avec sa méthode statique CreateInstance qui permet d'instancier un objet à partir d'un Type.

    Si on continue le code ci dessous, on aura :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    object monObjet = System.Activaror.CreateInstance(monType);
    Comme tu peux le voir, on récupère un instance de type Object qui est la classe de base du framework Dotnet, tout objet dérive du type Object que tu le veuilles ou pas, tu n'as pas le choix

    Il ne te reste plus qu'à caster correctement l'objet précédemment instancié. Comme tu peux le voir dans le code que je t'ai proposé hier, j'ai casté l'objet en DataObject directement dans la classe du même nom. La raison est que ça te permet d'avoir un code générique que tu n'auras pas besoin de re-écrire dans ta classe Company, ni dans User, encore moins dans une autre classe.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DataObject monDataObject = monObjet as DataObject;
    Cependant, si tu désires de spécialiser ton code dans la classe User par exemple, rien ne t'empêche de caster l'objet en User.

    Au passage, je viens de remarquer uen faute de ma part dans la méthode FindAll que je t'ai proposé ; Dedans, j'utilise des types User alors que le code doit être générique pour ne pas se soucier du type dont il a affaire, pour cela, j'aurais du écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public List<DataObject> FindAll()
    {
     ...
     List<DataObject> objDataObjects = new List<DataObject>(); // Et non List<User> objUsers = new List<User>();
    }
    Voila, en espérant ne pas m'être trop étalé, n'hésite pas si il reste des points sombres (je ne sais pas du tout si tu as des bonnes notions de tout ce qui est héritage et compagnie).

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Sinon tu peux utiliser LINQ to SQL... c'est moins générique, mais c'est tellement pratique de créer son mapping objet/relationnel en quelques clics...
    Par contre seul SQL Server est complètement supporté du moins jusqu'à ce que les éditeurs des autres SGBD nous sortent le provider ad hoc...

  6. #6
    Membre régulier
    Profil pro
    Développeur Web
    Inscrit en
    Décembre 2004
    Messages
    97
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2004
    Messages : 97
    Points : 89
    Points
    89
    Par défaut
    Un grand merci, Cardi, avec toutes ces belles paroles, j'ai quasi plus qu'à mettre en musique

    J'ai hâte de m'y mettre, ça va être chouette à implémenter tout ça.

    Merci, TomLev, pour ton information mais comme tu le précises avec "LINQ to SQL" seul SQLServer est supporté...pour l'instant

  7. #7
    Membre régulier
    Profil pro
    Développeur Web
    Inscrit en
    Décembre 2004
    Messages
    97
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2004
    Messages : 97
    Points : 89
    Points
    89

  8. #8
    Membre régulier
    Profil pro
    Développeur Web
    Inscrit en
    Décembre 2004
    Messages
    97
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2004
    Messages : 97
    Points : 89
    Points
    89
    Par défaut
    Bonjour,

    Tous se passe bien, j'arrive à faire ce que je souhaite.

    Travailler de la sorte, ça risque pas d'être lourd au niveau performance ? si je dois recomposer mes objets à chaque fois ?

    Bonne soirée,

    Philippe

  9. #9
    Membre expert
    Avatar de hed62
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2007
    Messages
    2 029
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 029
    Points : 3 134
    Points
    3 134
    Par défaut
    Si, mais si c'est le seul moyen ... Et je pense que tu ne verra pas trop la difference, sauf si tu ne cesse d'instancier des centaines d'objets de la sorte.

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 547
    Points : 627
    Points
    627
    Par défaut
    Salut,

    pour les perfs, il est sur que les mecanismes de la reflexion ne sont pas connus pour leur rapidité , mais comme dit au dessus, des fois tu es obligé d'y avoir recours. Vois si la perte de perf est sensible sur ton appli, et essaie de mettre en cache tes données autant que tu peux pour eviter la reconstruction au maximum.

    edit : precision

  11. #11
    Membre expert
    Avatar de hed62
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2007
    Messages
    2 029
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 029
    Points : 3 134
    Points
    3 134
    Par défaut
    "cacher" ... On va dire "mettre en cache" pour etre sur d'etre bien compris

    Bon ok je pinaille ...

  12. #12
    Membre régulier
    Profil pro
    Développeur Web
    Inscrit en
    Décembre 2004
    Messages
    97
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2004
    Messages : 97
    Points : 89
    Points
    89
    Par défaut
    Bonjour,

    Merci, pour vos intervention

    Ce qui commence à m'inquiéter, c'est que tous les objets de l'application seront basés sur cette classe dataObject(dans laquelle je définis toutes les méthodes de base findAll, loadAll, countAll, load, ...)

    Si dans une page de l'appli, j'ai un listing de 50 Users, je vais devoir, pour complétés les propriétés des 50 Users, passer dans cette boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    ...
    // On est sur la ligne courante, on va donc récupérer chaque valeur grâce à objFieldsMap
    foreach(string fieldname in objFieldsMap.Values)
    {
    object value = objDataReader[fieldname];
     
    // Maintenant, on va remplir la bonne propriété de l'objet objObjectToFill grâce à la réflexion
    System.Reflection.PropertyInfo objPropertyInfo = this.GetType().GetProperty(objFieldsMap[fieldName]);
    objPropertyInfo.SetValue(objObjectToFill, value, null);
    }
    ...
    Avec ce système, je vais peut-être droit dans le mur...

    Bonne journée,

    Philippe

Discussions similaires

  1. nommer un objet à partir d'une variable String
    Par kobrapercussions dans le forum Langage
    Réponses: 12
    Dernier message: 13/03/2007, 13h19
  2. Réponses: 7
    Dernier message: 29/12/2006, 12h56
  3. Réponses: 21
    Dernier message: 22/06/2006, 21h11
  4. Réponses: 6
    Dernier message: 18/01/2006, 16h26
  5. Generer des objets aleatoirement sur une carte
    Par K20 dans le forum Langage
    Réponses: 13
    Dernier message: 24/12/2005, 16h19

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