如何使用反射获取调用方法的名称和类型?

174

2
最高票答案已经过时。现在的语言直接支持此功能。请参见 https://dev59.com/wXVC5IYBdhLWcg3w1Exq#9621581。 - Andrew Rondeau
3
但这并不能解决获取类型的问题。 - Christoph Meißner
5个回答

446
public class SomeClass
{
    public void SomeMethod()
    {
        StackFrame frame = new StackFrame(1);
        var method = frame.GetMethod();
        var type = method.DeclaringType;
        var name = method.Name;
    }
}

现在假设您有另一个类,就像这样:

public class Caller
{
   public void Call()
   {
      SomeClass s = new SomeClass();
      s.SomeMethod();
   }
}
name将会是"Call",type将会是"Caller"。 更新:两年后我仍然得到了点赞。 在.NET 4.5中,现在有一种更简单的方法来完成这个操作。你可以利用CallerMemberNameAttribute
继续使用之前的示例:
public class SomeClass
{
    public void SomeMethod([CallerMemberName]string memberName = "")
    {
        Console.WriteLine(memberName); // Output will be the name of the calling method
    }
}

10
这是一个很好的解决方案,但你需要记住,在发布版本中除非禁用JIT方法内联,否则它不一定会返回你期望的答案。 - Greg Beech
7
在.NET 3.5解决方案中,你应该在SomeMethod上方添加[MethodImpl(MethodImplOptions.NoInlining)]以避免内联。将false传递给构造函数还可以防止从PDB文件加载文件名/行数据,加快StackTrace的构建速度。 - bart
43
感谢您更新答案,点赞加一。 - Joshua Drake
13
值得注意的是,使用 [CallerMemberName] 方案时,编译器会全权处理整个过程,因此在运行时不需要实际反射,这有助于提高性能。 - Grochni
36
真遗憾没有[CallerTypeName]可以获取调用方法的声明类型... - cube45
显示剩余9条评论

22
您可以使用StackTrace,然后从中获取反射类型。
StackTrace stackTrace = new StackTrace();           // get call stack
StackFrame[] stackFrames = stackTrace.GetFrames();  // get method calls (frames)

StackFrame callingFrame = stackFrames[1];
MethodInfo method = callingFrame.GetMethod();
Console.Write(method.Name);
Console.Write(method.DeclaringType.Name);

相关 https://dev59.com/wXVC5IYBdhLWcg3w1Exq - Pakk

13

其实可以通过当前的堆栈跟踪数据和反射来完成这项操作。

public void MyMethod()
{
     StackTrace stackTrace = new System.Diagnostics.StackTrace();
     StackFrame frame = stackTrace.GetFrames()[1];
     MethodInfo method = frame.GetMethod();
     string methodName = method.Name;
     Type methodsClass = method.DeclaringType;
}

StackFrame数组的1索引可以给出调用MyMethod方法的方法名称。


7

原则上,这是可能的,但不是免费的。

您需要创建一个StackTrace,然后您可以查看调用堆栈的StackFrame


7
技术上,你可以使用StackTrace,但这非常慢,并且很多时候无法给出你期望的答案。这是因为在发布版本中,可能会发生优化,导致某些方法调用被删除。因此,在发布版本中,你无法确定stacktrace是否“正确”。
实际上,在C#中没有绝对可靠或快捷的方法来解决这个问题。你真的应该问问自己为什么需要这样做,以及如何设计你的应用程序,使你能够在不知道是哪个方法调用它的情况下完成你想做的事情。

1
这是 A. 一个调试版本,并且 B. 调用其他程序集。通过 System.Diagnostics.Process 启动其他程序所需的时间远远超过使用 StackFrame 类所产生的任何开销。 - Billy ONeal
1
我正在进行这项工作是为了自动配置测试套件。 - Billy ONeal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接