Obtenir tous les messages d’InnerException (s)?

Existe-t-il un moyen d’écrire un code de type “main courte” LINQ pour accéder à tous les niveaux d’InnerException (s) d’Exception? Je préférerais l’écrire au lieu d’appeler une fonction d’extension (comme ci-dessous) ou d’hériter de la classe Exception .

 static class Extensions { public static ssortingng GetaAllMessages(this Exception exp) { ssortingng message = ssortingng.Empty; Exception innerException = exp; do { message = message + (ssortingng.IsNullOrEmpty(innerException.Message) ? ssortingng.Empty : innerException.Message); innerException = innerException.InnerException; } while (innerException != null); return message; } }; 

Malheureusement, LINQ ne propose pas de méthodes capables de traiter des structures hiérarchiques, mais uniquement des collections.

J’ai en fait quelques méthodes d’extension qui pourraient vous aider. Je n’ai pas le code exact en main mais ils sont quelque chose comme ça:

 // all error checking left out for brevity // aka, linked list style enumerator public static IEnumerable FromHierarchy( this TSource source, Func nextItem, Func canContinue) { for (var current = source; canContinue(current); current = nextItem(current)) { yield return current; } } public static IEnumerable FromHierarchy( this TSource source, Func nextItem) where TSource : class { return FromHierarchy(source, nextItem, s => s != null); } 

Dans ce cas, vous pouvez le faire pour énumérer les exceptions:

 public static ssortingng GetaAllMessages(this Exception exception) { var messages = exception.FromHierarchy(ex => ex.InnerException) .Select(ex => ex.Message); return Ssortingng.Join(Environment.NewLine, messages); } 

Tu veux dire quelque chose comme ca?

 public static class Extensions { public static IEnumerable GetInnerExceptions(this Exception ex) { if (ex == null) { throw new ArgumentNullException("ex"); } var innerException = ex; do { yield return innerException; innerException = innerException.InnerException; } while (innerException != null); } } 

De cette façon, vous pourriez LINQ sur toute votre hiérarchie d’exceptions, comme ceci:

 exception.GetInnerExceptions().Where(e => e.Message == "Oops!"); 

Que diriez-vous de ce code:

 private static ssortingng GetExceptionMessages(this Exception e, ssortingng msgs = "") { if (e == null) return ssortingng.Empty; if (msgs == "") msgs = e.Message; if (e.InnerException != null) msgs += "\r\nInnerException: " + GetExceptionMessages(e.InnerException); return msgs; } 

Usage:

 Console.WriteLine(e.GetExceptionMessages()) 

Exemple de sortie:

Il n’y avait pas de point d’extrémité à l’écoute à http: //nnn.mmm.kkk.ppp: 8000 / routingservice / router qui pouvait accepter le message. Cela est souvent causé par une adresse incorrecte ou une action SOAP. Voir InnerException, si présent, pour plus de détails.

InnerException: Impossible de se connecter au serveur distant

InnerException: aucune connexion n’a pu être établie car la machine cible l’a activement refusée 127.0.0.1:8000

Je sais que c’est évident, mais peut-être pas pour tous.

 exc.ToSsortingng(); 

Cela passera par toutes vos exceptions internes et retournera tous les messages, mais avec la trace de la stack, etc.

LINQ est généralement utilisé pour travailler avec des collections d’objects. Cependant, sans doute, dans votre cas, il n’y a pas de collection d’objects (mais un graphique). Donc, même si un code LINQ est possible, à mon humble avis, ce serait plutôt compliqué ou artificiel.

D’un autre côté, votre exemple ressemble à un exemple principal où les méthodes d’extension sont réellement raisonnables. Sans parler de problèmes tels que la réutilisation, l’encapsulation, etc.

Je restrais avec une méthode d’extension, même si je l’ai peut-être implémentée de la manière suivante:

 public static ssortingng GetAllMessages(this Exception ex) { if (ex == null) throw new ArgumentNullException("ex"); SsortingngBuilder sb = new SsortingngBuilder(); while (ex != null) { if (!ssortingng.IsNullOrEmpty(ex.Message)) { if (sb.Length > 0) sb.Append(" "); sb.Append(ex.Message); } ex = ex.InnerException; } return sb.ToSsortingng(); } 

Mais c’est en grande partie une question de goût.

Je ne pense pas, exception n’est pas un IEnumerable, donc vous ne pouvez pas effectuer une requête linq sur un seul.

Une méthode d’extension pour renvoyer les exceptions internes fonctionnerait comme ceci

 public static class ExceptionExtensions { public static IEnumerable InnerExceptions(this Exception exception) { Exception ex = exception; while (ex != null) { yield return ex; ex = ex.InnerException; } } } 

Vous pouvez ensuite append tous les messages en utilisant une requête linq comme ceci:

 var allMessageText = ssortingng.Concat(exception.InnerExceptions().Select(e => e.Message + ",")); 

Pour append à d’autres, vous pouvez laisser l’utilisateur décider comment séparer les messages:

  public static ssortingng GetAllMessages(this Exception ex, ssortingng separator = "\r\nInnerException: ") { if (ex.InnerException == null) return ex.Message; return ex.Message + separator + GetAllMessages(ex.InnerException, separator); } 
  public static ssortingng GetExceptionMessage(Exception ex) { if (ex.InnerException == null) { return ssortingng.Concat(ex.Message, System.Environment.NewLine, ex.StackTrace); } else { // Retira a última mensagem da pilha que já foi retornada na recursividade anterior // (senão a última exceção - que não tem InnerException - vai cair no último else, retornando a mesma mensagem já retornada na passagem anterior) if (ex.InnerException.InnerException == null) return ex.InnerException.Message; else return ssortingng.Concat(ssortingng.Concat(ex.InnerException.Message, System.Environment.NewLine, ex.StackTrace), System.Environment.NewLine, GetExceptionMessage(ex.InnerException)); } } 
 public static class ExceptionExtensions { public static IEnumerable GetAllExceptions(this Exception ex) { Exception currentEx = ex; yield return currentEx; while (currentEx.InnerException != null) { currentEx = currentEx.InnerException; yield return currentEx; } } public static IEnumerable GetAllExceptionAsSsortingng(this Exception ex) { Exception currentEx = ex; yield return currentEx.ToSsortingng(); while (currentEx.InnerException != null) { currentEx = currentEx.InnerException; yield return currentEx.ToSsortingng(); } } public static IEnumerable GetAllExceptionMessages(this Exception ex) { Exception currentEx = ex; yield return currentEx.Message; while (currentEx.InnerException != null) { currentEx = currentEx.InnerException; yield return currentEx.Message; } } } 

Je vais juste laisser la version la plus concise ici:

 public static class ExceptionExtensions { public static ssortingng GetMessageWithInner(this Exception ex) => ssortingng.Join($";{ Environment.NewLine }caused by: ", GetInnerExceptions(ex).Select(e => $"'{ e.Message }'")); public static IEnumerable GetInnerExceptions(this Exception ex) { while (ex != null) { yield return ex; ex = ex.InnerException; } } }