当登录c#时,我如何才能知道调用当前方法的方法的名称?我知道所有关于System.Reflection.MethodBase.GetCurrentMethod(),但我想在堆栈跟踪中走一步。我考虑过解析堆栈跟踪,但我希望找到一种更清晰、更显式的方式,比如Assembly.GetCallingAssembly(),但用于方法。


当前回答

我们也可以用来找到调用者。

假设你有一个你定义的方法:

public void MethodA()
    {
        /*
         * Method code here
         */
    }

你想找到它的调用者。

1. 改变方法签名,这样我们就有了一个Action类型的参数(Func也可以):

public void MethodA(Action helperAction)
        {
            /*
             * Method code here
             */
        }

2. Lambda名称不是随机生成的。规则似乎是:> <CallerMethodName>__X 其中CallerMethodName被前面的函数替换,X是一个索引。

private MethodInfo GetCallingMethodInfo(string funcName)
    {
        return GetType().GetMethod(
              funcName.Substring(1,
                                funcName.IndexOf("&gt;", 1, StringComparison.Ordinal) - 1)
              );
    }

3.当我们调用MethodA时,Action/Func参数必须由调用方方法生成。 例子:

MethodA(() => {});

4. 在MethodA内部,我们现在可以调用上面定义的helper函数,并找到调用方方法的MethodInfo。

例子:

MethodInfo callingMethodInfo = GetCallingMethodInfo(serverCall.Method.Name);

其他回答

通常,您可以使用System.Diagnostics. stacktrace类来获取System.Diagnostics。然后使用GetMethod()方法获取System.Reflection.MethodBase对象。然而,这种方法有一些注意事项:

它表示运行时堆栈——优化可以内联一个方法,并且您不会在堆栈跟踪中看到该方法。 它不会显示任何本机帧,所以即使有机会您的方法被本机方法调用,这也将不起作用,而且实际上目前没有可用的方法来做到这一点。

(注:我只是在扩展Firas Assad提供的答案。)

也许你正在寻找这样的东西:

StackFrame frame = new StackFrame(1);
frame.GetMethod().Name; //Gets the current method name

MethodBase method = frame.GetMethod();
method.DeclaringType.Name //Gets the current class name

我使用的另一种方法是向所讨论的方法添加参数。例如,使用void Foo(string context)而不是void Foo()。然后传入一些表示调用上下文的惟一字符串。

如果您只需要调用者/上下文进行开发,您可以在发布之前删除参数。

我们可以对阿萨德先生的代码(目前公认的答案)稍加改进,只实例化我们实际需要的帧而不是整个堆栈:

new StackFrame(1).GetMethod().Name;

这可能会执行得更好一些,尽管在所有的可能性中,它仍然需要使用整个堆栈来创建单个帧。此外,它仍然有Alex Lyman指出的同样的警告(优化器/本机代码可能会破坏结果)。最后,你可能想要检查以确保新的StackFrame(1)或. getframe(1)不返回null,因为这种可能性看起来不太可能。

请看这个相关问题: 您可以使用反射来查找当前正在执行的方法的名称吗?

注意,由于要进行优化,这样做在发布代码中是不可靠的。此外,在沙盒模式(网络共享)下运行应用程序根本不允许您获取堆栈帧。

考虑面向方面的编程(AOP),比如PostSharp,它不是从代码中调用,而是修改代码,从而始终知道它的位置。