Восстановление исключения в C#

Я использую Ranorex, инструмент автоматизации тестирования, основанный на С#, и у меня есть вопрос: обработка исключений и повторное создание исключения. Я новичок в программировании на С#, поэтому, пожалуйста, потерпите меня! Рассмотрим следующий код:

Дочерний класс/метод..

try
{
    do something;
    'unhandled exception on line 150'
}

catch (exception)
{
    throw;
}

родительский класс/метод

try
{
     childmethod();
}

catch (exception ex)
{
    report.info("Info",ex.Stacktrace);
}

Что я хотел бы сделать, так это сообщить номер строки, в которой произошло исключение, в дочернем классе/методе, но в обработчике исключений родительского класса. Таким образом, в каждом дочернем классе/методе мы можем просто повторно сгенерировать (выбросить) исключение обратно в мастер-класс/метод (т. е. тестовый пример в терминах Ranorex). В родительском обработчике исключений у нас есть другие задачи, такие как отчет о деталях системы, закрытие приложения и провал теста. Мы хотим сделать это только в одном месте, поэтому поместим класс верхнего уровня. Однако, используя приведенный выше код, stracktrace показывает номер строки в дочернем обработчике исключений, который выдает повторно, а также номер строки, в которой был вызван дочерний метод. Также было бы полезно, если бы мы могли просто извлечь из трассировки стека что-то в формате вроде

Class = 'class name' & Method = 'method name' & Line Num = 'line num' 

а не все сообщение трассировки стека.

Мы используем .net v4.0

Спасибо за помощь.

Трассировки стека:

The stacktrace information is: at System.Data.DataRow.GetDataColumn(String columnName)
at System.Data.DataRow.get_Item(String columnName)
at ABCTest.SUD.Plat.NewFU.NewFUUserCode.MainMethod(String testDataInstanceId) in c:\Ranorex Local Code\ABCTest\ABCTest\SUD\Plat\NewFU\NewFUUserCode.cs:line 103
at ABCTest.SUD.Plat.NewFU.NewFUUserCode.MainMethod(String testDataInstanceId) in c:\Ranorex Local Code\ABCTest\ABCTest\SUD\Plat\NewFU\NewFireFUUserCode.cs:line 130
at ABCTest.Tests.ManageFAndS.ManACA_IO_One.MainMethod() in c:\Ranorex Local Code\ABCTest\ABCTest\Tests\ManageFAndS\ManACA_IO_One.cs:line 59

person rockOn123    schedule 07.08.2013    source источник
comment
Вы понимаете, что вам придется распространять файлы .pdb, чтобы увидеть номера строк в исключениях?   -  person Matthew Watson    schedule 07.08.2013
comment
@MatthewWatson, но это очень помогает, и я говорю здесь по опыту   -  person No Idea For Name    schedule 07.08.2013


Ответы (1)


Здесь http://weblogs.asp.net/fmarguerie/archive/2008/01/02/rethrowing-exceptions-and-preserving-the-full-call-stack-trace.aspx есть решение . Я не уверен, что буду использовать его в своем коде, потому что он основан на недокументированном методе (но он все еще работает в .NET 4.0).

private static void PreserveStackTrace(Exception exception)
{
    MethodInfo preserveStackTrace = typeof(Exception).GetMethod("InternalPreserveStackTrace",
        BindingFlags.Instance | BindingFlags.NonPublic);
    preserveStackTrace.Invoke(exception, null);
}

static void MethodChild()
{
    try
    {
        throw new ArgumentException();
    }
    catch (Exception ex)
    {
        // Very important! Do it before rethrowing
        PreserveStackTrace(ex);
        throw;
    }
}

Этот ответ на SO объяснил проблему: у вас не может быть двух кадров стека одного и того же метода. Один метод = один кадр стека.

Чтобы получить информацию о том, где возникло исключение, вы можете использовать StackTrace. класс:

StackTrace st = new StackTrace(ex, true);
StackFrame frame = st.GetFrame(0);
MethodBase method = frame.GetMethod();

// What you want!
string methodName = method.Name;
string className = method.DeclaringType.FullName;
int lineNumber = frame.GetFileLineNumber();

передача исключения конструктору и true в качестве второго параметра.

person xanatos    schedule 07.08.2013
comment
Спасибо за информацию. Приведенная выше информация правильно дает мне имена методов и классов, однако номер строки по-прежнему дает мне номер строки в дочернем обработчике исключений, где повторно создается исключение. Есть 2 кадра. Кадр 0 предназначен для дочернего метода, а кадр 1 — для родительского метода. Я поместил трассировку стека в исходный пост. - person rockOn123; 07.08.2013
comment
@TimGONELLA Вы добавили PreserveStackTrace(ex); перед каждым rethrow? - person xanatos; 07.08.2013
comment
Да, я поместил его перед повторным вызовом в дочернем обработчике исключений. Таким образом, кадр o дает мне строку 130, а кадр 1 дает мне строку 59. В то время как мне нужна строка 103 в трассировке стека. - person rockOn123; 07.08.2013
comment
@TimGONELLA Я вижу, что в NET 4.5 есть другие решения: stackoverflow.com/a/17091351/613130 ИЛИ вы можете попробовать руководство PreserveStackFrame stackoverflow.com/a/2085377/613130 (работает без использования недокументированных функций) - person xanatos; 07.08.2013
comment
спасибо @Xanatos. К сожалению, мы не можем перейти на .Net 4.5. PreserveStackFrame мне непонятен, но я попробую. - person rockOn123; 07.08.2013