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 :

Handler Generique d'Exceptions


Sujet :

C#

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 11
    Points : 5
    Points
    5
    Par défaut Handler Generique d'Exceptions
    Bien le bonjour et bravo à tous les contributeurs de ce forum qui me sert enormement dans mon travail...

    Je ne suis pas un pro des templates et donc je me pose une question: comment implementer la classe TraceAndReThrowStrategy pour qu elle prenne en compte n importe quel type d exception passée au handler generique ?

    J'avais pensé au début faire quelque chose comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public class TraceAndReThrowStrategy : IErrorHandlingStrategy < Exception >
    {
      public void Handle (Exception _exception_in)
      {
         // du code
      }
    }
    Et plus tard d'appeler mon handler en faisant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    try { ... }
    catch (IOException ex)
    {
      ExceptionHandler<Exception, TraceAndReThrowStrategy> hdler = new ExceptionHandler<Exception, TraceAndReThrowStrategy>();
     
      // cast
      hdler.Handle( (Exception) ex);
    }
    Ca marche mais c est pas terrible car je perds le detail de mon exception lors du cast.

    De plus j'aimerais pouvoir avoir un traitement different par type d exception, par exple pouvoir tracer la requete SQL dans le cas d une SQLException (si ca existe), le nom du fichier pour une IOException, le Exception.Message dans le cas general, etc.

    Je ne vois vraiment pas comment rendre TraceAndReThrowStrategy generique à son tour tout en gardant la syntaxe de l article à savoir :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ExceptionHandler hdler = new ExceptionHandler < IOException,TraceAndReThrowStrategy >();
    	hdler.handle(ex);
    Merci d'avance pour votre aide, j avoue que je m arrache un peu les cheveux

  2. #2
    Membre averti
    Inscrit en
    Décembre 2008
    Messages
    256
    Détails du profil
    Informations personnelles :
    Âge : 47

    Informations forums :
    Inscription : Décembre 2008
    Messages : 256
    Points : 311
    Points
    311
    Par défaut
    De plus j'aimerais pouvoir avoir un traitement different par type d exception, par exple pouvoir tracer la requete SQL dans le cas d une SQLException (si ca existe), le nom du fichier pour une IOException, le Exception.Message dans le cas general, etc.
    La gestion des exceptions fournie par le Framework est déjà assez complète.
    Quel intérêt as-tu à implémenter ce gestionnaire d'exceptions générique ?

    Si je peux me permettre de te donner un seul conseil : Keep it simple !
    Il y a toujours au moins deux solutions à un problème.

    http://software-design-development.blogspot.com/

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par Gold Bug Voir le message
    La gestion des exceptions fournie par le Framework est déjà assez complète.
    Quel intérêt as-tu à implémenter ce gestionnaire d'exceptions générique ?

    Si je peux me permettre de te donner un seul conseil : Keep it simple !
    C est sur, mais pour certains cas precis j'ai besoin de declencher des traitements sur certaines exceptions... Par exemple un cas typique : j ecris en base de données mais je me prends une erreur parce que la table est en lecture seule... Cela peut tres bien arriver car j utilise de la replication entre plusieurs bases, c est une replication multi master ou chaque table est gerée par un seul maitre, si je veux ecrire dans cette table je dois dire a mon appli de bien choisir la base ou elle doit se connecter... Sauf que la config peut changer en cas de failover... Donc typiquement si je me prends cette erreur, je dois analyser le code d erreur et dire à mon appli d attendre quelques secondes le temps que le failover finissent de se mettre en place, puis de relire la config du cluster et recommencer l ecriture...

    C est le genre de code tres specifique que j ai envie d ecrire à un endroit... et pas dans chaque try/catch

    Par contre, je peux tres bien aussi vouloir juste tracer l erreur et quitter l appli... Voire meme appliquer une autre strategie qui consistera à envoyer un mail à l admin, tracer l erreur et quitter...

    Bref j ai envie de decrire ces strategies dans des classes et donner au developpeur la possibilité de les appeler simplement via ce handler generique... Comme ca si le developpeur a envie de catcher l erreur, il appelle simplement le handler et declenche le scenario predefini...

    Et du coup je trouve l idee de l article tres puissante....

    Typiquement pour le TraceAndExitStrategy je fais maintenant un truc du style :

    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
     
     
    public class TraceAndExitStrategy : IErrorHandlingStrategy < Exception >
    {
       public void Handle (Exception ex)
       {
          string message = ex.Message;
          Type type = ex.GetType();
     
          if ( ex is ORMQueryExecutionException)
          {
             message += "\n Executed query was: " + ( (ORMQueryExecutionException) ex).QueryExecuted;
          }
     
          Trace.WriteLine (message);
          Trace.Close();
          Process.GetCurrentProcess().Kill()
      }
    }
    Donc si c est une ORMQueryExecutionException j ai la requete SQL sinon j ai que le message...

    Vous en pensez quoi ? Je veux dire, est ce que c est la bonne methode pour implementer la Strategy et la rendre generique, ou est ce qu il y a plus intelligent ?

    Parce que du coup dans ce cas de figure seule cette syntaxe compilera:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ExceptionHandler hdler = new ExceptionHandler < Exception,TraceAndReThrowStrategy >();
    et pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ExceptionHandler hdler = new ExceptionHandler < ORMQueryExecutionException,TraceAndReThrowStrategy >();

    merci
    michael

  4. #4
    Rédacteur
    Avatar de Paul Musso
    Profil pro
    Inscrit en
    Août 2008
    Messages
    368
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Août 2008
    Messages : 368
    Points : 443
    Points
    443
    Par défaut
    Bonjour,

    Tu peux par exemple implémenter la méthode Handle ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      public void Handle (Exception _exception_in)
      {
         if (_exception_in is IOException)
         {
             // Code gestion IOException
         }
         else if (_exception_in is SQLException)
         {
             // Code gestion SQLException
         }
         // etc ...
      }
    Cependant je trouve vraiment pas ça terrible comme design ...

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par Paul Musso Voir le message
    Bonjour,

    Cependant je trouve vraiment pas ça terrible comme design ...
    Je crois qu on est d accord sur ce point

    Ou alors j avais pensé à carrement faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class MyStrategy: IErrorHandlingStrategy <Exception>, IErrorHandlingStrategy<SqlException>
     
    public void Handle (Exception _exception_in)
      {
           // du code specifique
      }
     
    public void Handle (SqlException _exception_in)
      {
           // du code specifique
      }
    }
    C'est mieux vous pensez ?

  6. #6
    Membre averti
    Inscrit en
    Décembre 2008
    Messages
    256
    Détails du profil
    Informations personnelles :
    Âge : 47

    Informations forums :
    Inscription : Décembre 2008
    Messages : 256
    Points : 311
    Points
    311
    Par défaut
    Le plus élégant serait de pouvoir dériver d'une classe qui implémente ta gestion d'erreur.

    Donc une fois n'est pas coutume, je pense que C++ serait plus adapté que C# pour l'implémentation de ce pattern car il supporte l'héritage multiple.
    Il y a toujours au moins deux solutions à un problème.

    http://software-design-development.blogspot.com/

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Je suis pas sur de comprendre... Ca voudrait dire que une strategie devrait pouvoir deriver de plusieurs autres ? J aurais une strategie qui trace, une qui rollback, une qui quitte l appli et je construirais un scenario en heritant de ces 3 classes ?

    J imaginais faire un peu la meme chose, a savoir construire des strategies de base et les composer dans l appel a mon handler de maniere sequencielle (trace puis rollback puis display message puis exit)...

    Sachant que ya plus d une chance sur 2 que je n'ai pas compris ton message

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Finalement partant de cette idée j ai decidé de creer une classe abstraite de base qui implemente l interface pour le type de base System.Exception

    Puis mon handler gere maintenant une collection de Strategy et implemente methode Add prenant en parametre une StrategyBase (ma classe de base abstraite).

    Lorsque j appelle la methode Handle sur chaque strategy pour un type d exception donné, je parcours la methode de la classe et si j en trouve une qui a la bonne signature j appelle celle ci, sinon j appelle la methode de base Handle(System.Exception) en faisant un cast.

    Ceci pour eviter d avoir à se demander si cette Strategy gere ou non le type d excpetion que je suis en train de catcher.

    A la base je suis pas censé gérer des centaines d exceptions de la sorte donc ca devrait pas trop ralentir mon execution...

    voila ca vous parait crado ou pas ?

    merci

  9. #9
    Membre averti
    Inscrit en
    Décembre 2008
    Messages
    256
    Détails du profil
    Informations personnelles :
    Âge : 47

    Informations forums :
    Inscription : Décembre 2008
    Messages : 256
    Points : 311
    Points
    311
    Par défaut
    Tu veux pas poster une partie des sources qu'on visualise à quoi ça ressemble stp ?
    Il y a toujours au moins deux solutions à un problème.

    http://software-design-development.blogspot.com/

  10. #10
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par Gold Bug Voir le message
    Tu veux pas poster une partie des sources qu'on visualise à quoi ça ressemble stp ?
    Of course

    Mon interface :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    namespace Biopacs.Framework.Exceptions
    {
        public interface IErrorHandlingStrategy <ExceptionType>
        {
            void Handle(ExceptionType _exception_in);
        }
    }
    Ma classe de base:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    namespace Biopacs.Framework.Exceptions
    {
        public abstract class ErrorHandlingStrategyBase: IErrorHandlingStrategy<Exception>
        {
            public abstract void Handle(Exception _exception_in);
        }
    }
    Un exemple de strategie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     public class DisplayAndExitStategy : ErrorHandlingStrategyBase, IErrorHandlingStrategy<ORMQueryExecutionException>
        {
     
            public override void Handle(Exception _exception_in)
            {
              ...
            }
     
            public void Handle(ORMQueryExecutionException_exception_in)
            {
              ...
            }
    }
    Le code foireux du handler

    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
        public class ExceptionHandler<ExceptionType>
        where ExceptionType : Exception
        {
            private ArrayList strategies;
     
            public ExceptionHandler()
            {
                strategies = new ArrayList();
                //m_strategy = new ErrorHandlingStrategyType();
            }
     
            public void Add(ErrorHandlingStrategyBase strategy)
            {
                strategies.Add(strategy);
            }
            public void Handle(ExceptionType _exception_in)
            {
                Type exType = _exception_in.GetType();
                if (exType.IsSubclassOf(typeof(Exception)))
                {
                    foreach (ErrorHandlingStrategyBase m_strategy in strategies)
                    {
                        Type t = m_strategy.GetType();
                        MethodInfo[] mi = t.GetMethods();
     
                        bool found = false;
     
                        foreach (MethodInfo m in mi)
                        {
                            if (m.Name == "Handle")
                            {
                                ParameterInfo[] pi = m.GetParameters();
     
                                if (pi.Length == 1)
                                    if (pi[0].GetType() == exType)
                                    {
                                        m_strategy.Handle(_exception_in);
                                        found = true;
                                        break;
                                    }
                            }
                        }
     
                        if (!found)
                            m_strategy.Handle((Exception)_exception_in);
                    }
                }
                else
                {
                    foreach (ErrorHandlingStrategyBase m_strategy in strategies)
                        m_strategy.Handle(_exception_in);
                }
            }
     
     
        }

  11. #11
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Petit bug :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
                                
                                if (pi.Length == 1)
                                    if (pi[0].ParameterType == exType)
                                    {
                                        m_strategy.Handle(_exception_in);
                                        found = true;
                                        break;
                                    }

  12. #12
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Bon ben ca marche toujours pas, peu importe le type d exception que je passe à mon handler il appelle toujours la methode Handle(Exception _exception_in)...

    Meme si il existe une methode Handle(SqlException _exception_in) et que je lui passe une exception du bon type il appelle systematiquement la premiere...

    Je comprends pas pourquoi il choisi pas la fonction avec la bonne signature....

    heeeeeelp

  13. #13
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 11
    Points : 5
    Points
    5
    Par défaut
    Bon alors pour ceux que ca interesse, voila le code qui marche...

    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
        public class ExceptionHandler<ExceptionType>
        where ExceptionType : Exception
        {
            private ArrayList strategies;
     
            public ExceptionHandler()
            {
                strategies = new ArrayList();
                //m_strategy = new ErrorHandlingStrategyType();
            }
     
            public void Add<ErrorHandlingStrategyType>(ErrorHandlingStrategyType strategy)
                where ErrorHandlingStrategyType: ErrorHandlingStrategyBase
            {
                strategies.Add(strategy);
            }
     
            public void Handle(ExceptionType _exception_in)
            {
                foreach (object m_strategy in strategies)
                {
                    Handle(_exception_in, m_strategy);
                }
            }
     
            public void Handle(ExceptionType _exception_in, object m_strategy)
            {
     
                MethodInfo method = m_strategy.GetType().GetMethod("Handle", new Type[] { _exception_in.GetType() });
     
                if (method == null)
                {
                    method = this.GetType().GetMethod("Handle", new Type[] { typeof(Exception) });
                }
     
                object caller = Activator.CreateInstance(m_strategy.GetType());
     
     
                method.Invoke(caller, new object[] { _exception_in });
     
            }
     
     
        }
    La methode Add est devenue generique mais impose que le type herite de la classe "strategie" de base... Ceci afin d etre sur qu elle implemente une methode Handle (System.Exception)

    Puis j utilise de la vraie reflection, a savoir je parcours ma collection de strategies, je recupere la methode (dans la stratege courante) qui a la bonne signature en fonction du type d exception que je suis en train de gerer, puis (astuce trouvée sur le net pour eviter une erreur d execution) j instancie un nouvel objet dont le type est le meme que celui de la strategie que je viens de depiler, et j invoke la methode qui va bien et la ca marche

    Et si je trouve pas la methode j invoque celle qui prend en parametre System.Exception

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

Discussions similaires

  1. gérer une exception envoyée par un handler de thread
    Par floopi51 dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 01/04/2010, 15h06
  2. [C#] Exception Handler
    Par diaboloche dans le forum Windows Forms
    Réponses: 4
    Dernier message: 04/11/2008, 14h36
  3. redéfinition exception handler Swing
    Par zais_ethael dans le forum AWT/Swing
    Réponses: 8
    Dernier message: 15/09/2008, 12h07
  4. Réponses: 4
    Dernier message: 24/10/2007, 12h16

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