Извлечение имени вызывающего метода из метода
Возможный дубликат:
Как найти метод, который вызвал текущий метод?
У меня есть метод в объекте, который вызывается из нескольких мест внутри объекта. Есть быстрый и простой способ получить имя метода, называемого этим популярным методом.
Псевдокод ПРИМЕР:
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
, но я действительно не любил запускать всю трассировку стека каждый раз, когда вызывается этот метод.
Ответы
Ответ 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
, не можете определить параметр или что-то, что бы передать нужную вам информацию. (Или положить в базовый класс или что-то еще...)