Получение метода, из которого был вызван метод?

Можно ли в PostError определить имя вызывающего метода "Eat Pizza"? Думаю, я мог бы передать «EatPizza» в качестве одного из аргументов, но это потребовало бы изменений при каждом изменении имени метода (ненужное обслуживание). Но тогда я даже не смог найти имя метода «EatPizza» в контексте «EatPizza» (используя stacktrace, getframe, getmethod).

public void EatPizza(Pizza p){
    if(p==null){ //A arbitrary made up error
        Utilities.PostError();
    }
    else{
        p.Slices -= 1;
    }
}

...

public void PostError(){
    //Basically posting to database the name of the method
    //Tried this, didn't work: (new StackTrace(true)).GetFrame(5).GetMethod().Name
    //Is it possible to determine the calling method name "Eat Pizza" in this context?
}

Когда я пробую разные значения (от 0 до StackTrace.FrameCount-1) в StackTrace.GetFrame, я получаю следующие значения, когда мне просто нужно «EatPizza»:

.ctor
ThreadStart
Main
_nExecuteAssembly
RunUsersAssemblyDebugInZone

person sooprise    schedule 14.04.2011    source источник
comment
Вы знаете, что генерирование исключения дает вам трассировку стека и является рекомендуемым способом обработки ошибок. По какой причине вы этого не делаете? При необходимости вы можете вызвать PostError в блоке catch.   -  person driis    schedule 14.04.2011
comment
Единственное, что я заметил, это то, что вы передаете 5 в GetFrame. Я думаю, вам нужен 0 для текущего кадра и 1 для предыдущего кадра. Но я также предполагаю, что вы используете это как демонстрацию того, что вы пробовали, а не буквального кода, который вы пробовали.   -  person SirPentor    schedule 14.04.2011
comment
@driis, хорошо, выглядит неплохо. Теперь у меня есть метод, который принимает аргумент Exception и отправляет Exception.StackTrace. Мне нравится это решение :)   -  person sooprise    schedule 14.04.2011


Ответы (2)


Вы были на правильном пути, создав объект StackTrace, но, похоже, вы неправильно поняли аргумент для GetFrame. Фреймы нумеруются от самого нижнего фрейма, поэтому:

  • GetFrame(0) вернет PostError
  • GetFrame(1) вернет вызывающего абонента PostError

Так что просто попробуйте это:

var trace = new StackTrace(true);
WriteToDB(trace.GetFrame(1).GetMethod().Name);

Лично я бы предпочел получить всю трассировку стека, а не только вызывающего, поэтому я бы сделал следующее:

var trace = new StackTrace(true);
WriteToDB(trace.ToString());
person JSBձոգչ    schedule 14.04.2011
comment
+1 Если вы собираетесь регистрировать ошибки с частичной трассировкой, почему бы не включить все это целиком и получить в свое распоряжение общую картину? - person Pete M; 14.04.2011
comment
+1, да, все это имеет смысл. Трассировка стека содержит достаточно информации для моих целей регистрации ошибок, спасибо! - person sooprise; 14.04.2011

Можно ли в PostError определить имя вызывающего метода "Eat Pizza"? Думаю, я мог бы передать «EatPizza» в качестве одного из аргументов, но это потребовало бы изменений при каждом изменении имени метода (ненужное обслуживание).

Вызов PostError во всех методах, в которых что-то может пойти не так, также является «ненужным обслуживанием». Это также усложняет выполнение вашей программы, потому что вам придется проверять наличие ошибок повсюду, а процессы высокого уровня должны будут проверять, успешно ли завершились процессы низкого уровня.

Лучше использовать структуры обработки исключений, предоставляемые CLR и C #.

Точное место, в котором произошла ошибка, сохраняется в свойстве исключения StackTrace.

pubic void BigDinnerEatingProcess()
{
    try
    {
         WhateverHappensAtTheTopLevel();
    }
    catch (PizzaNotDeliveredException ex)
    {
         Utilities.PostError(ex);
         MessageBox.Show("Dinner was not eaten. Please make sure the pizza is delivered.");
    }
}

public void EatPizza(Pizza p)
{
    if (p == null)
        throw new PizzaNotDeliveredException();
    p.RemoveOneSlice();
}

private void PostError(Exception ex)
{
    string errorLocation = ex.StackTrace;
    //...
}
person Jeffrey L Whitledge    schedule 14.04.2011
comment
+1 за ненужное усложнение. @sooprise Что, если бы вы решили реорганизовать свой метод ведения журнала, и StackTrace.GetFrame в итоге оказался на 2 уровня, а не на 1, как сейчас? Затем вам придется вручную настроить +1 кадры по всему вашему коду. - person bottlenecked; 14.04.2011