C# 如何获取包含调用当前方法的方法的类的名称?

C# 如何获取包含调用当前方法的方法的类的名称?,c#,C#,我有一个要求,我需要知道类ApicController的名称,它有一个方法GetMethod,该方法由另一个方法OtherMethod从另一个类OtherClass调用 为了帮助解释这一点,我希望下面的伪代码片段能有所帮助 ApiController.cs OtherClass.cs 我所尝试的: 我已经看过了,答案会让我得到调用方法OtherMethod,而不是拥有该方法的类ApiController 我尝试了[CallerMemberName]并使用了StackTrace属性,但这些属性无法

我有一个要求,我需要知道类ApicController的名称,它有一个方法GetMethod,该方法由另一个方法OtherMethod从另一个类OtherClass调用

为了帮助解释这一点,我希望下面的伪代码片段能有所帮助

ApiController.cs OtherClass.cs 我所尝试的:

我已经看过了,答案会让我得到调用方法OtherMethod,而不是拥有该方法的类ApiController 我尝试了[CallerMemberName]并使用了StackTrace属性,但这些属性无法获取方法的类名
所以可以这样做

new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().DeclaringType.Name
表示调用堆栈上的方法,索引1提供包含当前执行方法的直接调用方的帧,在本例中为ApiController.GetMethod

现在有了框架,然后通过调用StackFrame.GetMethod检索该框架的MethodInfo,然后使用MethodInfo的DeclaringType属性获取定义该方法的类型,即ApicController

转到堆栈的上一级,查找该方法,并从该方法获取类型。这避免了您需要创建一个完整的StackTrace,这是非常昂贵的

如果需要完全限定的类名,可以使用FullName

编辑:边缘案例,突出以下评论中提出的问题

如果启用了编译优化,则调用方法可能是内联的,因此您可能无法获得预期的值。学分: 异步方法被编译到状态机中,所以同样,您可能无法得到预期的结果。学分:
您可以通过以下代码实现这一点

首先,您需要使用System.Diagnostics添加名称空间

stackTrace的实例取决于您的实现环境。您可以在本地或全局定义它

您可以在不创建StackTrace实例的情况下使用下面的方法


试试这个,它可能会帮助您

为什么不简单地将名称作为构造函数参数传递呢?与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);
    }
}

可能对您有用。如果您知道如何获取该方法,那么您也知道哪个类具有该方法。返回的信息不仅仅是一个方法的名称,它是该方法的所有信息,包括classnew StackTrace.GetFrame1.GetMethod.DeclaringType.FullName如果您只是使用它来打印名称,就像在您的示例中一样,那么它可能没问题。如果你打算根据你得到的答案应用任何逻辑,我会认真地建议你重新审视你的设计。根据调用堆栈的确切形状神奇地改变其行为的方法令人费解。例如,想象一下,如果ApicController有某种形式的helper类,并且它将对OtherMethod的调用移动到helper中,会发生什么。请下次给出一个。这很有效,谢谢!我赞赏其他答案中的解释,尤其是其中一个,因为它深入地解释了正在发生的事情。但是,正如你所指出的,这个答案似乎是最便宜的,并且得到了同样的结果,应该是其他寻求实现同样目标的人的一个很好的参考。这不是100%可靠的。如果启用优化,则GetMethod可能是内联的,不会显示在堆栈跟踪中。堆栈包含的返回地址通常可能与调用方地址不同。请看,为了避免任何混淆,您行中的GetMethod与OP的ApiController.GetMethod无关,对吗?是的,只是巧合,OP创造了一个名为GetMethod的方法,而StackFrame也有这个方法。这也是一个可行的解决方案,但我想看看如何在不将名称作为参数传递的情况下实现它。
new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().DeclaringType.Name
using System.Diagnostics;

var className = new StackFrame(1).GetMethod().DeclaringType.Name;
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);
    }
}
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);
    }
}
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);
    }
}