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 :

Classes imbriquées, remonter les évènements


Sujet :

C#

  1. #1
    Membre actif
    Homme Profil pro
    Architecte technique
    Inscrit en
    Février 2004
    Messages
    477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Service public

    Informations forums :
    Inscription : Février 2004
    Messages : 477
    Points : 223
    Points
    223
    Par défaut Classes imbriquées, remonter les évènements
    Bonjour,

    J'ai un soucis et j'aimerai savoir ce que vous me proposeriez comme solution:

    Imaginons ces 2 classes.

    La classe B joue le rôle de connecteur vers un serveur.
    Lorsque j'appelle la méthode "connect", je me connecte au serveur et je renvoie une information qui indique que la connexion a été établie.

    La classe A utilise une instance de mon connecteur.
    Par contre je ne souhaite pas que mon connecteur soit visible si un développeur utilise une instance de A, donc je mets la propriété en privée.

    Par contre je veux que mon développeur puisse avoir les retours des évènements qui se génère depuis la classe B, en utilisant l'instance de A.
    Je n'ai rien trouvé de mieux que dupliquer les définitions de mes délégués et évènements. Auriez vous une meilleure idée ?


    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
     
     
    // -- Utilisation des classes par un développeur tiers dans son application
    // ------------------------------------------------------------------------------
    A myClientConnection = new A();
    myClientConnection.onConnectionSuccess += connection_successfull;
     
     
    public class A
    {
            public delegate void connectionDlg();
            public event connectionDlg onConnectionSuccess;
     
            private B connector; 
     
            public A()
            {
                  connector= new B();
                  connector.onConnectionSuccess += connection_ok;
                  connector.connect();
            }
     
            private void connection_ok()
            {
                if(onConnectionSuccess != null)
                 onConnectionSuccess();
            }
    }
     
    public class B : ICallback
    {
          public delegate void connectionDlg();
          public event connectionDlg onConnectionSuccess;
     
          public void connect()
          {
                 if(onConnectionSuccess != null)
                 onConnectionSuccess();
          }
     
          public void testConnection(){} // -- issue de l'interface
     
    }

  2. #2
    Membre confirmé Avatar de jacky01
    Profil pro
    Développeur .NET
    Inscrit en
    Juin 2007
    Messages
    537
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juin 2007
    Messages : 537
    Points : 527
    Points
    527
    Par défaut
    Salut,

    Pourquoi ne pas dérivé A de B pour éviter les copies de code.

    En espérant avoir compris correctement la problématique.
    Je fais ce que je dis et je dis ce que je veux .

  3. #3
    Membre actif
    Homme Profil pro
    Architecte technique
    Inscrit en
    Février 2004
    Messages
    477
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Service public

    Informations forums :
    Inscription : Février 2004
    Messages : 477
    Points : 223
    Points
    223
    Par défaut
    Parce que ça n'aurait pas de sens ...
    En gros ma classe A, c'est un "client" et ma classe B c'est le "connecteur" qui permet de se connecter au serveur.
    Donc nous sommes plutôt dans une composition. D'un point de vue MERISE je ne peux pas dire mon connecteur est un client mais plutôt mon client possède un connecteur.

  4. #4
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 898
    Points : 1 915
    Points
    1 915
    Par défaut
    Bonjour,

    Il parait difficile ne pas répéter certaines parties si tu veux exposer des événements de connexion sans exposer la classe qui effectue la connexion elle-même. Petite suggestion d'architecture :

    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
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    using System;
    using System.Threading.Tasks;
     
    namespace DataConnection
    {
        public class ConnectionSuccessEventArgs : EventArgs { }
        public delegate void ConnectionSuccess(object sender, ConnectionSuccessEventArgs e);
     
        public class ConnectionFailedEventArgs : EventArgs
        {
            public ConnectionFailedEventArgs(Exception exception) => Exception = exception;
     
            public Exception Exception { get; }
        }
        public delegate void ConnectionFailed(object sender, ConnectionFailedEventArgs e);
     
        public interface IConnector : IDisposable
        {
            void Connect();
     
            event ConnectionSuccess ConnectionSuccess;
            event ConnectionFailed ConnectionFailed;
        }
     
        internal class InternalDbConnector : IConnector // internal to be visible only in within the assembly
        {
            // connection handling
            public event ConnectionSuccess ConnectionSuccess;
            public event ConnectionFailed ConnectionFailed;
     
            public void Connect()
            {
                try
                {
                    Task.Delay(1000); // custom db connection code
                    ConnectionSuccess?.Invoke(this, new ConnectionSuccessEventArgs()); // everything went fine
                }
                catch (Exception e)
                {
                    ConnectionFailed?.Invoke(this, new ConnectionFailedEventArgs(e)); // an error occured
                }
            }
     
     
            // disposable pattern
            private bool _disposed;
     
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this); // ignore finalizer since we're already disposing
            }
     
            protected void Dispose(bool disposing)
            {
                if (_disposed) return;
                if (disposing)
                {
                    // dispose managed resources
                }
                // free unmanaged resources
                _disposed = true;
            }
     
            ~InternalDbConnector() => Dispose(false);
        }
     
        public interface IDataConnector<T> : IConnector
        {
            T GetData();
        }
     
        public class DataConnector<T> : IDataConnector<T>
        {
            private readonly IConnector _connector;
     
            public DataConnector() : this(new InternalDbConnector()) { }
            public DataConnector(IConnector connector)
            {
                _connector = connector;
                _connector.ConnectionSuccess += OnConnectionSuccess;
                _connector.ConnectionFailed += OnConnectionFailed;
            }
     
            // connection handling
            public event ConnectionSuccess ConnectionSuccess;
            public event ConnectionFailed ConnectionFailed;
     
            public void Connect() => _connector.Connect();
     
            private void OnConnectionSuccess(object sender, ConnectionSuccessEventArgs e) => ConnectionSuccess?.Invoke(this, e);
     
            private void OnConnectionFailed(object sender, ConnectionFailedEventArgs e) => ConnectionFailed(this, e);
     
     
            // IDataConnector<T>
            public T GetData() => default(T);
     
     
            // disposable pattern
            private bool _disposed;
     
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this); // ignore finalizer since we're already disposing
            }
     
            private void Dispose(bool disposing)
            {
                if (_disposed) return;
     
                _connector.ConnectionSuccess -= OnConnectionSuccess;
                _connector.ConnectionFailed -= OnConnectionFailed;
                if (disposing)
                {
                    // dispose managed resources
                    _connector.Dispose();
                }
                // free unmanaged resources
                _disposed = true;
            }
     
            ~DataConnector() => Dispose(false);
        }
    }
    Des ajustements sont possible, par exemple préciser les interfaces selon que l'on est sur une connexion base de donnée ou une connexion de données plus haut niveau. Je n'ai pas précisé un modèle async pour ne pas complexifier, par contre j'ai ajouté le modèle IDisposable qui me paraît important quand on réserve des ressources externes.

    N'hésite pas à poser des questions si certains points ne sont pas clair ou nécessitent des explications.

  5. #5
    Membre chevronné
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 898
    Points : 1 915
    Points
    1 915

Discussions similaires

  1. [C#]Remonter des événements dans des classes imbriquées
    Par Kcirtap dans le forum Windows Forms
    Réponses: 9
    Dernier message: 14/12/2013, 12h43
  2. [prototype] gérer les événements dans une classe
    Par nawac dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 10/05/2010, 18h44
  3. [AC-2007] Classe ne voit pas les évènements du formulaire
    Par Maxence HUBICHE dans le forum VBA Access
    Réponses: 2
    Dernier message: 08/04/2009, 22h10
  4. Réponses: 3
    Dernier message: 01/02/2009, 00h05
  5. Faire "remonter" les données dans des requetes imbriquées
    Par Earthwormjim dans le forum Requêtes
    Réponses: 5
    Dernier message: 30/08/2006, 17h37

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