How to get the name of the class which contains th

2020-02-26 14:56发布

I have a requirement where I need to know the name of the class (ApiController) which has a method (GetMethod) which is called by another method (OtherMethod) from a different class (OtherClass).

To help explain this, I hope the below pseudo-code snippets help.

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*/)
    }
}

What I've tried:

  • I've looked at How can I find the method that called the current method? and the answers will get me the calling method (OtherMethod) but not the class (ApiController) which has that method
  • I tried [CallerMemberName] and using StackTrace properties but these don't get me the method's class name

标签: c#
4条回答
够拽才男人
2楼-- · 2020-02-26 15:39

So it can be done like this,

new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().DeclaringType.Name

StackFrame represents a method on the call stack, the index 1 gives you the frame that contains the immediate caller of the currently executed method, which is ApiController.GetMethod() in this example.

Now you have the frame, then you retrieve the MethodInfo of that frame by calling StackFrame.GetMethod(), and then you use the DeclaringType property of the MethodInfo to get the type in which the method is defined, which is ApiController.

查看更多
乱世女痞
3楼-- · 2020-02-26 15:39

You can achieve this by below code

First you need to add namespace 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);
    }
}

The instance of stackTrace is depend upon your implementation environment. you may defined it locally or globally

OR

You may use below method without creating StackTrace instance

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);
    }
}

Try this may it help you

查看更多
趁早两清
4楼-- · 2020-02-26 15:52
using System.Diagnostics;

var className = new StackFrame(1).GetMethod().DeclaringType.Name;

Goes to the previous level of the Stack, finds the method, and gets the type from the method. This avoids you needing to create a full StackTrace, which is expensive.

You could use FullName if you want the fully qualified class name.

Edit: fringe cases (to highlight the issues raised in comments below)

  1. If compilation optimizations are enabled, the calling method may be inlined, so you may not get the value you expect. (Credit: Johnbot)
  2. async methods get compiled into a state machine, so again, you may not get what you expect. (Credit: Phil K)
查看更多
兄弟一词,经得起流年.
5楼-- · 2020-02-26 15:54

Why not simply pass the name as constructor parameter? This doesn't hide the dependency, unlike StackFrame/StackTrace.

For example:

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);
    }
}
查看更多
登录 后发表回答