Как получить имя класса, содержащего метод, который вызвал текущий метод?
У меня есть требование, когда мне нужно знать имя класса (ApiController), у которого есть метод (GetMethod), который вызывается другим методом (OtherMethod) из другого класса (OtherClass).
Чтобы помочь объяснить это, я надеюсь, что ниже описаны фрагменты псевдокода.
ApiController.cs
public class ApiController
{
public void GetMethod()
{
OtherMethod();
}
}
OtherClass.cs
public class OtherClass()
{
public void OtherMethod()
{
Console.WriteLine(/*I want to get the value 'ApiController' to print out*/)
}
}
Что я пробовал:
- Я посмотрел, как найти метод, называемый текущим методом? и ответы получат мне метод вызова (OtherMethod), но не класс (ApiController), который имеет этот метод
- Я попробовал
[CallerMemberName]
и использовал свойства StackTrace
но это не StackTrace
мне имя класса метода
Ответы
Ответ 1
using System.Diagnostics;
var className = new StackFrame(1).GetMethod().DeclaringType.Name;
Переход на предыдущий уровень стека, поиск метода и получение типа из метода. Это позволяет избежать необходимости создания полного StackTrace, что дорого.
Вы можете использовать FullName
если хотите получить полное имя класса.
Изменение: случайные случаи (чтобы выделить проблемы, поднятые в комментариях ниже)
- Если оптимизация компиляции включена, метод вызова может быть встроен, поэтому вы можете не получить ожидаемое значение. (Кредит: Джонбот)
-
async
методы скомпилируются в конечный автомат, так что опять же вы не можете получить то, что ожидаете. (Кредит: Фил К)
Ответ 2
Так что это можно сделать так,
new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().DeclaringType.Name
StackFrame представляет собой метод в стеке вызовов, индекс 1 дает вам фрейм, который содержит непосредственный вызывающий ApiController.GetMethod()
текущего выполняемого метода, который является ApiController.GetMethod()
в этом примере.
Сейчас у вас есть кадр, то вы извлечь MethodInfo
из этого кадра, вызвав StackFrame.GetMethod()
, а затем использовать DeclaringType
свойство MethodInfo
получить тип, в котором определен метод, который ApiController
.
Ответ 3
Вы можете достичь этого ниже кода
Сначала вам нужно добавить пространство имен, using System.Diagnostics;
public class OtherClass
{
public void OtherMethod()
{
StackTrace stackTrace = new StackTrace();
string callerClassName = stackTrace.GetFrame(1).GetMethod().DeclaringType.Name;
string callerClassNameWithNamespace = stackTrace.GetFrame(1).GetMethod().DeclaringType.FullName;
Console.WriteLine("This is the only name of your class:" + callerClassName);
Console.WriteLine("This is the only name of your class with its namespace:" + callerClassNameWithNamespace);
}
}
Экземпляр stackTrace
зависит от вашей среды реализации. вы можете определить его локально или глобально
ИЛИ ЖЕ
Вы можете использовать метод ниже, не создавая экземпляр StackTrace
public class OtherClass
{
public void OtherMethod()
{
string callerClassName = new StackFrame(1).GetMethod().DeclaringType.Name;
string callerClassNameWithNamespace = new StackFrame(1).GetMethod().DeclaringType.FullName;
Console.WriteLine("This is the only name of your class:" + callerClassName);
Console.WriteLine("This is the only name of your class with its namespace:" + callerClassNameWithNamespace);
}
}
Попробуйте, это поможет вам
Ответ 4
Почему бы просто не передать имя в качестве параметра конструктора? Это не скрывает зависимость, в отличие от StackFrame
/StackTrace
.
Например:
public class ApiController
{
private readonly OtherClass _otherClass = new OtherClass(nameof(ApiController));
public void GetMethod()
{
_otherClass.OtherMethod();
}
}
public class OtherClass
{
private readonly string _controllerName;
public OtherClass(string controllerName)
{
_controllerName = controllerName;
}
public void OtherMethod()
{
Console.WriteLine(_controllerName);
}
}