Comment puis-je ajouter un message à une exception sans perdre aucune information en C#?
J'ai le code suivant:
catch(Exception ex)
{
throw new FatalException("An error occurred while trying to load the XSLT file.", ex);
}
Cela, malheureusement, juste d'engloutir l'Exception. Je peux résoudre ce problème en procédant comme suit:
catch(Exception ex)
{
throw;
}
Mais je voudrais quand même d'inclure le message personnalisé pour les aider avec la journalisation des événements.
Comment puis-je ajouter ce message à l'exception sans perte d'information? (trace de la pile/symboles de debug, etc.)
- Ajouter l'exception d'origine comme un
InnerException
sur leFatalException
? - C'est à la fin de
throw new FatalException("message", ex)
. - Pourquoi voulez vous faire ce que montrer? Seul hic, les exceptions que vous pouvez faire quelque chose avec. Sinon, laisser bouillonner.
- Vous pouvez le faire pour ajouter un utilisateur-amical message qui peut être affiché à l'utilisateur, puis effectuez l'enregistrement sur votre propre. Si vous avez FatalException dériver de ApplicationException, vous serez en mesure de facilement identifier les Exceptions que vous avez ajouté des messages contre les Exceptions qui sont jetés n'importe où ailleurs dans le code.
- Ouais, le point de ce qui est essentiellement d'avoir une interface conviviale message (pour l'enregistrement), mais de conserver l'original de l'information de l'Exception (à des fins de débogage).
- Découlant de
ApplicationException
est la pratique recommandée dans le passé, mais n'est-ce pas plus. C'est parce que certains cadre des exceptions en fait dériver de cette classe trop. - Merci. J'ai pensé que j'avais lu ça récemment, mais mon boss a m'a juste dit de le faire. Je suppose qu'il n'arrivait pas sur que "mineur" changement dans la pratique. Ainsi, au lieu, faites votre propre base de classe d'Exception et de regarder pour le.
Vous devez vous connecter pour publier un commentaire.
Si vous avez juste besoin d'ajouter de l'information à l'exception d'origine, tels que de l'utilisateur, le message lisible ou des détails spécifiques qui vous seront utiles dans la traque de l'erreur, mais qui ne sera pas utile à l'utilisateur final, vous pouvez faire usage de l'Exception de Données de la propriété, qui est une paire clé/valeur dictionnaire.
Nous utilisons cette profondeur dans le but d'enregistrer des informations telles que le rapport n'ait été exécuté ou fichier qui est en cours de traitement afin que les opérations puissent déterminer exactement ce qui se passe au moment de l'erreur. L'utilisateur n'a pas besoin de ce détail, puisqu'ils travaillent directement avec la cause de l'échec.
Vous pouvez également l'utiliser pour transmettre un message en texte brut qui fait sens pour l'utilisateur. Le seul problème, c'est que vous aurez à effectuer des travaux supplémentaires dans votre journalisation ou de l'interface de l'utilisateur final afin d'en extraire les données et les rendre utiles au consommateur.
Par exemple, vous pourriez faire:
Ensuite dans le code côté client, vous pouvez le tester pour voir si UserMessage existe et, dans l'affirmative, de le présenter à l'utilisateur au lieu de l'Exception:
ex.Data["UserMessage"] += "An error occurred...";
de sorte que si l'un des niveaux inférieurs de code déjà ajouté un message, il serait ajouter du texte supplémentaire à elle au lieu de lancer uneArgumentException
ToString()
. C'est gênant si vous avez beaucoup de code existant qui stringifies une exception pour l'imprimer. Est-il un moyen pour organiserToString()
pour inclure toutes les infos, ou devrais-je faire quelque chose de différent pour vider une exception, comme le texte?Que l'Exception d'origine est toujours là.
Lorsque vous faites de votre enregistrement d'Exception, l'Exception que vous recevrez sera le FatalException que vous avez fait avec votre message. L'Exception d'origine est en
ex.InnerException
. Vous pouvez continuer à passer en revue InnerException jusqu'à ce qu'il est null pour obtenir toutes les informations de Trace de Pile, etc.En bref, ne pas.
Je suis sûr que vous pourriez trouver un moyen de contourner cela avec un peu de réflexion, mais je fortement vous mets en garde contre cela. Il va à l'encontre de la conception originale des exceptions .NET. Les Exceptions ne sont pas juste là pour les aider avec l'exploitation forestière, ils fournissent des informations sur l'origine d'une défaillance de l'application.
À l'aide de la première option est préférable, car elle garde la trace de la pile de l'exception d'origine, mais permet de fournir des informations supplémentaires en l'enveloppant dans une autre exception. Dans mon propre code, à chaque fois que je me connecte exceptions, ma fonction d'enregistrement répète à travers la propriété InnerException pour trouver tous les bits de l'information utile possible au sujet de l'erreur.
Juste au cas où quelqu'un a besoin d'une bonne réponse. La clé est d'utiliser AppDomain.CurrentDomain.FirstChanceException
L', vous pouvez créer un objet personnalisé avec IDisposable de mettre toutes les infos en elle. Et si une exception se produit alors FirstChanceException gestionnaire obtient de cette info et remplir Exception.Les données.
Utiliser Thread Local de Stockage pour le rendre thread-safe. Puis en bas de la ligne du code qui attrape il va obtenir les données et les enregistrer dans un fichier.
Exemple:
Google AsyncDiagnosticStack pour un bon exemple. https://github.com/StephenCleary/AsyncDiagnostics/blob/master/src/Nito.AsyncEx.AsyncDiagnostics/AsyncDiagnosticStack.cs