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 :

objet partagé entre plusieurs classes


Sujet :

C#

  1. #1
    Membre actif Avatar de grinder59
    Inscrit en
    Septembre 2005
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 707
    Points : 215
    Points
    215
    Par défaut objet partagé entre plusieurs classes
    Bonjour,

    Mon programme C# comporte plusieurs classes dont une particulière, la classe Log qui comporte toutes les propriétés et méthodes relatives aux logs de mon application et notamment :
    - l'instance de StreamWriter
    - une méthode OuvrirFichier
    - une méthode EcrireFichier
    - une méthode FermerFichier

    Afin d'optimiser les accès au fichier de log, je souhaiterai faire la chose suivante :

    dans mon programme principal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Log monLog = new Log();
    monLog.OuvrirFichier();
     
    // traitements faisant appel aux objets instances des autres classes et aux méthodes rattachées
     
    monLog.FermerFichier();
    Ainsi je ne fais qu'une ouverture / fermeture de mon fichier dans toute mon application !

    Je voudrais que les autres classes puissent utiliser l'objet monLog (pour utiliser la méthode EcrireFichier) mais sans devoir passer l'objet monLog en paramètre des méthodes de mes autres classes.

    Est-ce possible ? Comment faire ?

    Merci de votre aide !

  2. #2
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Plusieurs possibilités.

    1- Tu fais de ta classe Log une classe statique utilitaire pour la journalisation. Tu pourras ainsi y accéder de partout.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public static class Log
    {
        ...
    }
    Pas adapté si à un moment tu as besoin de gérer plusieurs journaux par contre.

    2- Tu stockes dans une classe statique (pour les données globales) une référence sur l'instance de la classe Log à utiliser dans l'application

    Même principe qu'avant en gros, sauf que tu pourras gérer plusieurs journaux. Avec par exemple des journaux par module de l'application (module d'import, d'export, ...).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public static class Global
    {
        public static Log JournalExport
        { 
            get { ... } 
            set { ... }       
        }
     
        public static Log JournalImport
        { 
            get { ... } 
            set { ... }
        } 
    }
    L'inconvénient pourrait être l'accès aux propriétés en écriture (set), à moins que tu puisses directement instancier les journaux dans le constructeur statique de la classe Global. Auquel cas cet inconvénient n'est plus.

    3- Tu fais de ta classe Log un singleton. Tu pourras ainsi faire comme avec la méthode 2, sachant que l'inconvénient de la méthode 2 disparait normalement.

  3. #3
    Membre actif Avatar de grinder59
    Inscrit en
    Septembre 2005
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 707
    Points : 215
    Points
    215
    Par défaut
    Merci de ta réponse !

    Si j'ai bien compris le principe du Singleton qui me semble la méthode la plus propre, il s'agit d'une classe qui n'a qu'une seule instance, c'est bien cela ?

    Ainsi lorsque toutes les instances de toutes les classes que je pourrais définir de mon Singleton seront une seule et unique instance (la même chose, le même objet, le même truc) ?

  4. #4
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Disons plutôt que le singleton permet de contrôler le nombre d'instances. Souvent il s'agit d'une seule instance, d'où le nom de singleton. Mais on peut très bien imaginer un singleton qui fourni une instance par thread par exemple (ça existe dans MapXtreme). Mais au final le but est de pouvoir accéder au(x) même(s) objet(s) de partout.

    On trouve pas mal de choses sur le singleton

    http://webman.developpez.com/article...rns/singleton/
    http://www.yoda.arachsys.com/csharp/singleton.html
    http://msdn.microsoft.com/fr-fr/library/ff650316.aspx
    ...

  5. #5
    Membre actif Avatar de grinder59
    Inscrit en
    Septembre 2005
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 707
    Points : 215
    Points
    215
    Par défaut
    Sauf erreur, je serai néanmoins obligé de récupérer l'instance à chaque début de méthode dans laquelle je loggue :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    log = Log.getInstance();
    Mais bon, c'est un moindre mal puisque ça me permet de ne gérer qu'un seul fichier avec un seul accès !

    Merci beaucoup.

  6. #6
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Non puisqu'il suffit de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Log.Instance.Ecrire(...);
    Utilise une propriété s'il n'y a qu'un seule instance, c'est plus naturel qu'une méthode GetInstance. L'utilisation d'une méthode est plus indiquée si tu gères plusieurs instances, un indexeur ferait l'affaire également.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Log.GetInstance("Import").Ecrire(...);
    Ou avec un indexeur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Log.Instance["Import"].Ecrire(...);

  7. #7
    Membre actif Avatar de grinder59
    Inscrit en
    Septembre 2005
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 707
    Points : 215
    Points
    215
    Par défaut
    Utilise une propriété s'il n'y a qu'un seule instance, c'est plus naturel qu'une méthode GetInstance. L'utilisation d'une méthode est plus indiquée si tu gères plusieurs instances, un indexeur ferait l'affaire également.
    Mais dans ces cas là, comment garantir l'unicité de l'instance ?

    Suivant l'un des liens que tu cites plus haut, je fais de la façon suivante :

    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
     
     private static Log instance = null;
     
            public static Log getInstance()
            {
                //lock permet de s’assurer qu’un thread n’entre pas dans une section critique du code pendant qu’un autre thread s’y trouve.  
                //Si un autre thread tente d’entrer dans un code verrouillé, il attendra, bloquera, jusqu’à ce que l’objet soit libéré.
                lock (myLock)
                {
                    // Si on demande une instance qui n’existe pas, alors on crée notre Log.
                    if (instance == null) instance = new Log();
                    // Dans tous les cas on retourne l’unique instance de notre Log.
                    return instance;
                }
            }

  8. #8
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Une propriété ce n'est rien d'autre qu'une méthode Get et éventuellement une méthode Set. Les propriétés sont juste plus "naturelles" à utiliser, mais une fois le code compilé ce sont des méthodes qu'on retrouve derrière.

    Une version thread-safe utilisant une propriété (c'est aussi dans les liens donnés plus tôt)
    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
    public sealed class Singleton
    {
        static readonly Singleton instance=new Singleton();
     
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Singleton()
        {
        }
     
        Singleton()
        {
        }
     
        public static Singleton Instance
        {
            get
            {
                return instance;
            }
        }
    }

  9. #9
    Membre actif Avatar de grinder59
    Inscrit en
    Septembre 2005
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 707
    Points : 215
    Points
    215
    Par défaut
    En effet, je m'étais arrêté avant, mea culpa...

    En revanche, plus ça va et plus c'est le brouillard...

    Suivant tes conseils, j'ai déclaré mon Singleton de la façon suivante :
    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
     
        public sealed class Log
        {
            public static readonly Log instance = new Log();
            public StreamWriter fichierLog = File.AppendText("log.txt"); 
     
            // constructeur statique
            static Log(){ }
     
            public static Log Instance
            {
                get
                {
                    return instance;
                }
            }
     
            public void ecritureFichier(string text)
            {
                fichierLog.WriteLine(text.ToString());
                fichierLog.Close();
            }
        }
    ça fonctionne, mais j'aurai besoin de quelques confirmations afin d'être sûr que je comprends bien ce que je code :

    La déclaration de l'instance unique est-elle bien faite dans cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    public static readonly Log instance = new Log();
    A quoi sert le constructeur static ?

    J'ai supprimé l'autre constructeur car dans la mesure où je définis le chemin vers mon fichier en propriété de la classe, je n'ai rien besoin d'autre ! Ce constructeur était-il utile ?

    Instance est bien la méthode qui permet de définir la propriété instance ?

    --------------------
    Edit :

    et en même temps, pour en revenir au sujet de base, vouloir créer 3 méthodes ouvrir / écrire / fermer n'a aucun intérêt puisque le log n'est pas consultable si le stream n'est pas fermé et que si il est fermé, je dois le réouvrir pour pouvoir réécrire dedans... mais la méthode du singleton me permet néanmoins de n'avoir qu'une seule instance de ce fichier de log !

  10. #10
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Pour commencer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public StreamWriter fichierLog = File.AppendText("log.txt");
    Ne pas mettre le champ en public. Tu n'en as pas besoin de l'extérieur, donc laisse le en privé.

    Les champs publics sont généralement réservés pour des constantes (const ou readonly) comme Int32.MinValue par exemple. Sinon les champs doivent être privés avec une propriété publique ou protégée pour l'accès. C'est le principe de l'encapsulation en POO.

    La déclaration de l'instance unique est-elle bien faite dans cette ligne ...
    Oui, ainsi que son intanciation.

    A quoi sert le constructeur static ?
    C'est une subtilité technique qui permet de rendre le système lazy, afin d'instancier les objets le plus tard possible. Tu trouveras plus d'infos sur le second lien à ce sujet.

    J'ai supprimé l'autre constructeur car dans la mesure où je définis le chemin vers mon fichier en propriété de la classe, je n'ai rien besoin d'autre ! Ce constructeur était-il utile ?
    Dans ton cas il n'est pas effectivement pas utile, le constructeur implicite par défaut suffit.

    Instance est bien la méthode qui permet de définir la propriété instance ?
    Instance est une propriété en lecture seule (get sans set) qui va permettre d'accéder à l'instance unique de ton objet.

    Sinon, lorsque tu fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public void ecritureFichier(string text)
    {
        fichierLog.WriteLine(text.ToString());
        fichierLog.Close();
    }
    Pas besoin d'appeler la méthode ToString() sur l'objet text car c'est déjà une string.
    Ensuite tu fermes le flux (méthode Close) donc les écritures suivantes généreront une exception. Il faudrait ouvrir, écrire et fermer le flux ou bien garder le flux ouvert en permanence.

    La dernière solution est peut être plus adaptée si tu écris très souvent dans le fichier, je ne sais pas trop.
    Sinon il faut prendre la première solution et à ce moment ton champ fichierLog n'est plus utile car tout se passera dans la méthode d'écriture. Quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public void WriteLine(string text)
    {
        using(StreamWriter fichierLog = File.AppendText("log.txt"))
        {
            fichierLog.WriteLine(text);
        }
    }
    Le mot clé using permet d'appeler automatiquement la méthode Dispose afin de libérer les ressources.

  11. #11
    Membre actif Avatar de grinder59
    Inscrit en
    Septembre 2005
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 707
    Points : 215
    Points
    215
    Par défaut
    Dans ton cas il n'est pas effectivement pas utile, le constructeur implicite par défaut suffit.
    Sauf si dans l'instanciation précédente, je voulais appeler un autre constructeur que le constructeur statique !

    Instance est une propriété en lecture seule (get sans set) qui va permettre d'accéder à l'instance unique de ton objet.
    merci pour le lien, j'ai besoin d'une explication complète et je trouvais pas la page associée !

    [...]La dernière solution est peut être plus adaptée si tu écris très souvent dans le fichier, je ne sais pas trop.[...]
    si je te suis bien, le moyen la plus adaptée, en cas de d'écritures fréquentes, est celle où la méthode contient l'ouverture, l'écriture et la fermeture du fichier ?

  12. #12
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Sauf si dans l'instanciation précédente, je voulais appeler un autre constructeur que le constructeur statique !
    Sauf si tu voulais appeler un autre constructeur tout court
    Le constructeur statique c'est un peu particulier et dans le cas du singleton si le constructeur statique est mis explicitement c'est uniquement une subtilité technique. En gros ne t'embête pas trop avec ça ^^

    si je te suis bien, le moyen la plus adaptée, en cas de d'écritures fréquentes, est celle où la méthode contient l'ouverture, l'écriture et la fermeture du fichier ?
    Non c'est le contraire, mais je me suis mal exprimé ^^
    Lorsque je disais la première/la dernière solution c'était en référence à
    Citation Envoyé par StormimOn
    Il faudrait ouvrir, écrire et fermer le flux ou bien garder le flux ouvert en permanence

  13. #13
    Membre actif Avatar de grinder59
    Inscrit en
    Septembre 2005
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 707
    Points : 215
    Points
    215
    Par défaut
    Sauf si tu voulais appeler un autre constructeur tout court
    Sauf que pour le coup, je n'ai que le constructeur static de dispo et j'appelle celui là ! (ou ai-je compris un truc de travers ?)

    Bon, en tous cas un grand merci pour toutes tes infos / liens / explications très utiles !!!

  14. #14
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Citation Envoyé par grinder59 Voir le message
    Sauf que pour le coup, je n'ai que le constructeur static de dispo et j'appelle celui là ! (ou ai-je compris un truc de travers ?)
    De travers ^^
    Supprime le constructeur statique de ton code, ça évitera de te mélanger les pinceaux

    Le constructeur statique est appelé automatiquement avant la première instanciation ou le premier accès à un membre statique. Tu n'as aucun contrôle sur le moment où le constructeur statique est exécuté.

    Comme je l'ai dit, dans l'exemple du singleton sur le second lien donné au tout début, c'est juste une subtilité technique pour une variante du pattern (relis l'article en question et la partie qui concerne le flag BeforeFieldInit si ça t'intéresse).

  15. #15
    Membre actif Avatar de grinder59
    Inscrit en
    Septembre 2005
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 707
    Points : 215
    Points
    215
    Par défaut
    ben donc y'a pas de constructeur ?
    c'est possible d'instancier une classe sans constructeur ?

  16. #16
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Il y a toujours un constructeur par défaut sauf si tu en déclares un de manière explicite. Plus d'infos : http://msdn.microsoft.com/fr-fr/libr...zh(VS.80).aspx

  17. #17
    Membre actif Avatar de grinder59
    Inscrit en
    Septembre 2005
    Messages
    707
    Détails du profil
    Informations forums :
    Inscription : Septembre 2005
    Messages : 707
    Points : 215
    Points
    215
    Par défaut
    OK, tout est clair maintenant !!!

    Merci encore et encore !!!

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

Discussions similaires

  1. [Débutant] Partager une même propriété entre plusieurs classes
    Par BasicZX81 dans le forum VB.NET
    Réponses: 4
    Dernier message: 09/09/2012, 15h56
  2. Partager du code entre plusieurs classes-filles
    Par gvdmoort dans le forum Débuter avec Java
    Réponses: 3
    Dernier message: 24/03/2012, 00h58
  3. Partager une variable entre plusieurs classes
    Par jasonpolakow dans le forum Windows Forms
    Réponses: 8
    Dernier message: 06/01/2011, 10h02
  4. Réponses: 6
    Dernier message: 09/11/2006, 10h29
  5. [MFC] objet commun a plusieurs classes
    Par Info42 dans le forum MFC
    Réponses: 4
    Dernier message: 11/05/2006, 18h52

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