我们可以使用反射来查找当前正在执行的方法的名称吗?

时间:2020-03-05 18:47:43  来源:igfitidea点击:

如标题所示:反射可以为我们提供当前正在执行的方法的名称。

由于海森堡问题,我倾向于不猜测。我们如何调用一个方法,该方法将告诉我们当前方法而不更改当前方法是什么?但我希望有人能证明我做错了。

更新:

  • 第2部分:是否可以将其用于查找属性的内部代码?
  • 第3部分:演出效果如何?

最后结果
我了解了MethodBase.GetCurrentMethod()。我还了解到,不仅可以创建堆栈跟踪,还可以仅创建所需的确切帧。

要在属性中使用它,只需使用.Substring(4)删除" set_"或者" get_"。

解决方案

回答

我认为我们应该可以通过创建StackTrace来实现。或者,就像@edg和@Lars M?hlum提到的那样,MethodBase.GetCurrentMethod()

回答

当然是。

如果我们想操纵一个对象,我实际上使用如下函数:

public static T CreateWrapper<T>(Exception innerException, params object[] parameterValues) where T : Exception, new()
{
    if (parameterValues == null)
    {
        parameterValues = new object[0];
    }

    Exception exception   = null;
    StringBuilder builder = new StringBuilder();
    MethodBase method     = new StackFrame(2).GetMethod();
    ParameterInfo[] parameters = method.GetParameters();
    builder.AppendFormat(CultureInfo.InvariantCulture, ExceptionFormat, new object[] { method.DeclaringType.Name, method.Name });
    if ((parameters.Length > 0) || (parameterValues.Length > 0))
    {
        builder.Append(GetParameterList(parameters, parameterValues));
    }

    exception = (Exception)Activator.CreateInstance(typeof(T), new object[] { builder.ToString(), innerException });
    return (T)exception;
}

这行:

MethodBase method     = new StackFrame(2).GetMethod();

沿着堆栈帧走动以找到调用方法,然后我们使用反射来获取传递给它的参数信息值,以用于通用错误报告功能。要获取当前方法,只需使用当前堆栈帧(1)即可。

正如其他人对当前方法名称所说的,我们还可以使用:

MethodBase.GetCurrentMethod()

我更喜欢遍历堆栈,因为如果从内部看该方法,无论如何它只会创建一个StackCrawlMark。在我看来,直接处理堆栈似乎更清晰

发布4.5之后,我们现在可以将[CallerMemberNameAttribute]用作方法参数的一部分,以获取方法名称的字符串,这在某些情况下可能会有所帮助(但实际上在上述示例中)

public void Foo ([CallerMemberName] string methodName = null)

这似乎主要是对INotifyPropertyChanged支持的解决方案,以前我们在整个事件代码中都乱扔了字符串。

回答

System.Reflection.MethodBase.GetCurrentMethod().Name;

http://msdn.microsoft.com/zh-CN/library/system.reflection.methodbase.getcurrentmethod.aspx

回答

在一个空的控制台程序的Main方法中尝试以下操作:

MethodBase method = MethodBase.GetCurrentMethod();
Console.WriteLine(method.Name);

控制台输出:
主要

回答

编辑:MethodBase可能是一种更好的方法,只是获得我们所在的方法(而不是整个调用堆栈)。不过,我仍然会担心内联。

我们可以在方法中使用StackTrace:

StackTrace st = new StackTrace(true);

然后看一下框架:

// The first frame will be the method you want (However, see caution below)
st.GetFrames();

但是,请注意,如果该方法是内联的,则不会进入我们认为的方法之内。我们可以使用属性来防止内联:

[MethodImpl(MethodImplOptions.NoInlining)]

回答

Lex提供的代码段有点长,所以我指出了重要的部分,因为没有其他人使用完全相同的技术:

string MethodName = new StackFrame(0).GetMethod().Name;

这应该向MethodBase.GetCurrentMethod()。Name技术返回相同的结果,但是仍然值得指出,因为我可以在自己的方法中使用上一个方法的索引1来实现一次该方法,然后从多个不同的属性调用它。同样,它只返回一帧,而不是整个堆栈跟踪:

private string GetPropertyName()
{  //.SubString(4) strips the property prefix (get|set) from the name
    return new StackFrame(1).GetMethod().Name.Substring(4);
}

它也是单线的;)

回答

这个怎么样:

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