Подтвердить что ты не робот

Извлечение имени вызывающего метода из метода

Возможный дубликат:
Как найти метод, который вызвал текущий метод?

У меня есть метод в объекте, который вызывается из нескольких мест внутри объекта. Есть быстрый и простой способ получить имя метода, называемого этим популярным методом.

Псевдокод ПРИМЕР:

public Main()
{
     PopularMethod();
}

public ButtonClick(object sender, EventArgs e)
{
     PopularMethod();
}

public Button2Click(object sender, EventArgs e)
{
     PopularMethod();
}

public void PopularMethod()
{
     //Get calling method name
}

Внутри PopularMethod() я хотел бы увидеть значение Main, если он был вызван из Main... Я хотел бы видеть "ButtonClick", если PopularMethod() был вызван из ButtonClick

Я смотрел на System.Reflection.MethodBase.GetCurrentMethod(), но это не вызовет меня вызывающий метод. Я посмотрел класс StackTrace, но я действительно не любил запускать всю трассировку стека каждый раз, когда вызывается этот метод.

4b9b3361

Ответ 1

Я не думаю, что это можно сделать без трассировки стека. Однако это довольно просто:

StackTrace stackTrace = new StackTrace();
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod();
Console.WriteLine(methodBase.Name); // e.g.

Однако, я думаю, вам действительно нужно остановиться и спросить себя, если это необходимо.

Ответ 2

В .NET 4.5/С# 5 это просто:

public void PopularMethod([CallerMemberName] string caller = null)
{
     // look at caller
}

Компилятор автоматически добавляет имя вызывающего абонента; так:

void Foo() {
    PopularMethod();
}

пройдет в "Foo".

Ответ 3

Это действительно очень просто.

public void PopularMethod()
{
    var currentMethod = System.Reflection.MethodInfo
        .GetCurrentMethod(); // as MethodBase
}

Но будьте осторожны, я немного скептически отношусь к тому, что инкрустация метода имеет какой-то эффект. Вы можете сделать это, чтобы убедиться, что компилятор JIT не будет мешать.

[System.Runtime.CompilerServices.MethodImpl(
 System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public void PopularMethod()
{
    var currentMethod = System.Reflection.MethodInfo
        .GetCurrentMethod();
}

Чтобы получить метод вызова:

[System.Runtime.CompilerServices.MethodImpl(
 System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public void PopularMethod()
{
    // 1 == skip frames, false = no file info
    var callingMethod = new System.Diagnostics.StackTrace(1, false)
         .GetFrame(0).GetMethod();
}

Ответ 4

Просто введите параметр

public void PopularMethod(object sender)
{

}

IMO: Если это достаточно хорошо для событий, для этого должно быть достаточно.

Ответ 5

Я часто обнаружил, что сам хочу этого, но всегда заканчиваю реорганизацию дизайна моей системы, поэтому я не получаю анти-шаблон "Хвост виляния собаки". Результат всегда был более надежной архитектурой.

Ответ 6

В то время как вы можете наиболее определенно проследить стек и понять его таким образом, я бы призвал вас переосмыслить ваш дизайн. Если ваш метод должен знать о каком-то "состоянии", я бы сказал, просто создайте перечисление или что-то еще, и возьмите это как параметр для вашего PopularMethod(). Что-то в этом роде. Основываясь на том, что вы публикуете, отслеживание стека будет чрезмерным IMO.

Ответ 7

Я думаю, вам нужно использовать класс StackTrace, а затем StackFrame.GetMethod() в следующем кадре.

Похоже, странно использовать Reflection. Если вы определяете PopularMethod, не можете определить параметр или что-то, что бы передать нужную вам информацию. (Или положить в базовый класс или что-то еще...)