Bạn phải lặp lại, và phải lặp lại, việc chuyển vòng lặp thành một chức năng riêng biệt sẽ rõ ràng hơn.
Tôi đã tạo một phương pháp mở rộng để giải quyết vấn đề này. Nó trả về danh sách tất cả các ngoại lệ bên trong của kiểu được chỉ định, đuổi theo Exception.InnerException và AggregateException.InnerExceptions.
Trong vấn đề cụ thể của tôi, việc theo đuổi các ngoại lệ bên trong phức tạp hơn bình thường, bởi vì các ngoại lệ đang được ném bởi các hàm tạo của các lớp đang được gọi thông qua phản xạ. Ngoại lệ mà chúng tôi đang bắt gặp có InnerException kiểu TargetInvocationException và các ngoại lệ mà chúng tôi thực sự cần xem xét đã bị chôn sâu trong cây.
public static class ExceptionExtensions
{
public static IEnumerable<T> innerExceptions<T>(this Exception ex)
where T : Exception
{
var rVal = new List<T>();
Action<Exception> lambda = null;
lambda = (x) =>
{
var xt = x as T;
if (xt != null)
rVal.Add(xt);
if (x.InnerException != null)
lambda(x.InnerException);
var ax = x as AggregateException;
if (ax != null)
{
foreach (var aix in ax.InnerExceptions)
lambda(aix);
}
};
lambda(ex);
return rVal;
}
}
Cách sử dụng khá đơn giản. Ví dụ: nếu bạn muốn biết liệu chúng tôi có gặp phải
catch (Exception ex)
{
var myExes = ex.innerExceptions<MyException>();
if (myExes.Any(x => x.Message.StartsWith("Encountered my specific error")))
{
}
}
LibraryException -> LibraryException -> LibraryException -> MyException
. Ngoại lệ của tôi luôn là ngoại lệ cuối cùng trên chuỗi và không có ngoại lệ bên trong của riêng nó.