Есть ли способ написать код «короткой руки» стиля LINQ для перехода на все уровни исключений InnerException (ы) исключения? Я бы предпочел написать его вместо того, чтобы называть функцию расширения (как показано ниже) или наследовать класс Exception
.Получение всех сообщений от InnerException (s)?
ответ
К сожалению LINQ не предлагает методы, которые могут обрабатывать иерархические структуры, только коллекции.
У меня есть некоторые методы расширения, которые могли бы помочь в этом. У меня нет точного кода в руке, но они что-то вроде этого:
// all error checking left out for brevity
// a.k.a., linked list style enumerator
public static IEnumerable<TSource> FromHierarchy<TSource>(
this TSource source,
Func<TSource, TSource> nextItem,
Func<TSource, bool> canContinue)
{
for (var current = source; canContinue(current); current = nextItem(current))
{
yield return current;
}
}
public static IEnumerable<TSource> FromHierarchy<TSource>(
this TSource source,
Func<TSource, TSource> nextItem)
where TSource : class
{
return FromHierarchy(source, nextItem, s => s != null);
}
Тогда в этом случае вы могли бы сделать это, чтобы перечислить через исключения:
public static string GetaAllMessages(this Exception exception)
{
var messages = exception.FromHierarchy(ex => ex.InnerException)
.Select(ex => ex.Message);
return String.Join(Environment.NewLine, messages);
}
Вы имеете в виду что-то вроде этого?
public static class Extensions
{
public static IEnumerable<Exception> GetInnerExceptions(this Exception ex)
{
if (ex == null)
{
throw new ArgumentNullException("ex");
}
var innerException = ex;
do
{
yield return innerException;
innerException = innerException.InnerException;
}
while (innerException != null);
}
}
Таким образом, вы могли бы LINQ над иерархией целых исключений, как это:
exception.GetInnerExceptions().Where(e => e.Message == "Oops!");
LINQ, как правило, используется для работы с коллекциями объектов. Однако, возможно, в вашем случае нет набора объектов (но графика). Поэтому, хотя некоторый код LINQ может быть возможен, ИМХО будет довольно запутанным или искусственным.
С другой стороны, ваш пример выглядит как пример, где методы расширения действительно разумны. Не говоря уже о таких вопросах, как повторное использование, инкапсуляция и т.д.
Я хотел бы остаться с методом расширения, хотя я мог бы реализовать это таким образом:
public static string GetAllMessages(this Exception ex)
{
if (ex == null)
throw new ArgumentNullException("ex");
StringBuilder sb = new StringBuilder();
while (ex != null)
{
if (!string.IsNullOrEmpty(ex.Message))
{
if (sb.Length > 0)
sb.Append(" ");
sb.Append(ex.Message);
}
ex = ex.InnerException;
}
return sb.ToString();
}
Но это во многом вопрос вкуса.
Я так не думаю, исключение не является IEnumerable, поэтому вы не можете выполнить запрос linq против одного самостоятельно.
метод расширения для возврата внутренние исключения будет работать как этот
public static class ExceptionExtensions
{
public static IEnumerable<Exception> InnerExceptions(this Exception exception)
{
Exception ex = exception;
while (ex != null)
{
yield return ex;
ex = ex.InnerException;
}
}
}
можно затем добавить все сообщения, используя Linq запрос следующим образом:
var allMessageText = string.Concat(exception.InnerExceptions().Select(e => e.Message + ","));
public static class ExceptionExtensions
{
public static IEnumerable<Exception> GetAllExceptions(this Exception ex)
{
Exception currentEx = ex;
yield return currentEx;
while (currentEx.InnerException != null)
{
currentEx = currentEx.InnerException;
yield return currentEx;
}
}
public static IEnumerable<string> GetAllExceptionAsString(this Exception ex)
{
Exception currentEx = ex;
yield return currentEx.ToString();
while (currentEx.InnerException != null)
{
currentEx = currentEx.InnerException;
yield return currentEx.ToString();
}
}
public static IEnumerable<string> GetAllExceptionMessages(this Exception ex)
{
Exception currentEx = ex;
yield return currentEx.Message;
while (currentEx.InnerException != null)
{
currentEx = currentEx.InnerException;
yield return currentEx.Message;
}
}
}
Как об этом коде:
private static string GetExceptionMessages(this Exception e, string msgs = "")
{
if (e == null) return string.Empty;
if (msgs == "") msgs = e.Message;
if (e.InnerException != null)
msgs += "\r\nInnerException: " + GetExceptionMessages(e.InnerException);
return msgs;
}
Использование:
Console.WriteLine(e.GetExceptionMessages())
Пример вывода:
Там не было конечной точкой прослушивания в http://nnn.mmm.kkk.ppp:8000/routingservice/router, которые могли бы принять сообщение. Это часто вызвано неправильным адресом или действием SOAP. Дополнительную информацию см. В InnerException, если имеется.
InnerException: Невозможно подключиться к удаленному серверу
InnerException: Подключение не может быть сделано, потому что целевая машина активно отказалась его 127.0.0.1:8000
Лично я большой поклонник рекурсии. Хорошее использование. –
Вы должны действительно рассмотреть возможность использования 'StringBuilder' здесь. Кроме того, метод расширения IMO должен вызывать «NullReferenceException» при вызове нулевой ссылки. – dstarkowski
Это работает действительно красиво! Очень подходящий вариант использования для рекурсивного программирования. – Shiva
Чтобы добавить к другим, вы можете захотеть, чтобы пользователю решить, о том, как отделить сообщения:
public static string GetAllMessages(this Exception ex, string separator = "\r\nInnerException: ")
{
if (ex.InnerException == null)
return ex.Message;
return ex.Message + separator + GetAllMessages(ex.InnerException, separator);
}
public static string GetExceptionMessage(Exception ex)
{
if (ex.InnerException == null)
{
return string.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 string.Concat(string.Concat(ex.InnerException.Message, System.Environment.NewLine, ex.StackTrace), System.Environment.NewLine, GetExceptionMessage(ex.InnerException));
}
}
Я знаю, что это очевидно, но, возможно, не для всех.
exc.ToString();
Это будет пройти через все ваши внутренние исключения и возвращает все сообщения, но вместе с трассировкой стека и т.д.
Yeh thats fine, если вы счастливы жить со всей полной трассировкой стека, которую вызывают с помощью ToString. Это часто не подходит для контекста, например, если сообщение идет к пользователю. С другой стороны, сообщение НЕ дает внутреннее сообщение об исключении (в отличие от ToString, который рекурсирует). То, что мы чаще всего хотим, - это несуществующий FullMessage, который является всем сообщением от родительских и внутренних исключений. – Ricibob
- 1. получение InnerException вызывает ошибки
- 2. Получение всех сообщений от устройства android
- 3. Получение сообщений от guid
- 4. Получение EPG от DVB-S
- 5. Получение последних сообщений от всех пользователей, использующих Entity Framework/LINQ
- 6. Подача всех сообщений от всех пользователей
- 7. Остановить получение сообщений от SubscriptionClient
- 8. Получение сообщений от ваших друзей
- 9. Получение сообщений от ребенка Windows
- 10. Получение всех возможных изменений сообщений об ошибках
- 11. Получение всех сообщений в электронной АСоип
- 12. получение всех сообщений facebook с помощью FQL
- 13. Ребус останавливает получение сообщений от RabbitMQ
- 14. Получение всех хештегов от пользователя
- 15. Получение всех данных от json?
- 16. Как создать наблюдаемый из непрочитанных сообщений от наблюдаемых всех сообщений
- 17. Получите lik.size от всех сообщений пользователя
- 18. C# InnerException в AggregateExpression
- 19. Получение сообщений Eclipse CDT от компилятора
- 20. android GCM Получение сообщений от нескольких устройств
- 21. Получение нескольких предупреждающих сообщений от поиска jsTree
- 22. Получение сообщений от kafka с помощью шторма
- 23. JMS-получение сообщений от удаленной Glassfish
- 24. ActiveMQ Не Получение сообщений от производителя
- 25. Получение последних сообщений в блоге от wordpress
- 26. Получение бэкэнд-флеш-сообщений от SPA-интерфейса
- 27. Получение сообщений от gRPC на Android-приложении
- 28. Android - Получение сообщений от AWS SQS
- 29. Получение списка всех активных сообщений в CAN-шине
- 30. Получение всех детей от узла Firebase-Android
Могу ли я спросить вас, почему вы хотите использовать что-то другое, чем методы расширения? Ваш код выглядит хорошо для меня, и он многократно используется в вашем коде. – ken2k
@ ken2k: Хотя вы не хотели бы создавать сообщения так, как он есть сейчас ... –
@JeffMercado Да, но в чем проблема с понятием «метод расширений»? – ken2k