你可以使用reflection来find当前正在执行的方法的名称?

像标题所示:可以reflection给你当前正在执行的方法的名称。

由于海森堡问题,我倾向于猜测。 你如何调用一个方法来告诉你当前的方法而不改变当前的方法? 但我希望有人能certificate我错了。

更新:

  • 第2部分:这可以用来查看一个属性的代码吗?
  • 第3部分:表演会是怎样的?

最后结果
我了解了MethodBase.GetCurrentMethod()。 我还了解到,我不仅可以创build堆栈跟踪,而且只需要创build我需要的确切帧即可。

要在一个属性中使用这个,只需要一个.Substring(4)来删除'set_'或'get_'。

从.NET 4.5开始,你也可以使用[CallerMemberName]

示例:属性设置器(回答第2部分):

protected void SetProperty<T>(T value, [CallerMemberName] string property = null) { this.propertyValues[property] = value; OnPropertyChanged(property); } public string SomeProperty { set { SetProperty(value); } } 

编译器将在调用处提供匹配的string文字,所以基本上没有性能开销。

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

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

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

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

这也是一个class轮;)

在一个空的控制台程序中,在Main方法里面试试这个:

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

控制台输出:
Main

当然是。

如果你想要一个对象来操作,我实际上使用这样一个函数:

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

沿着堆栈框架find调用方法,然后我们使用reflection来获取传递给它的参数信息值,以用于通用错误报告function。 要获得当前的方法,只需使用当前的堆栈帧(1)。

正如其他人所说的当前的方法名称,你也可以使用:

 MethodBase.GetCurrentMethod() 

我更喜欢走栈,因为如果从内部看这个方法,它只是简单地创build一个StackCrawlMark。 直接解决堆栈似乎更清楚

Post 4.5现在可以使用[CallerMemberNameAttribute]作为方法参数的一部分来获取方法名称的string – 这可能有助于在某些情况下(但实际上在上面的例子中)

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

这似乎主要是INotifyPropertyChanged支持的解决scheme,以前你的string散布在你的事件代码中。

编辑: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)] 

比较获取方法名称的方法 – 在LinqPad中使用任意时间结构 :

 void Main() { // from http://blogs.msdn.com/b/webdevelopertips/archive/2009/06/23/tip-83-did-you-know-you-can-get-the-name-of-the-calling-method-from-the-stack-using-reflection.aspx // and https://stackoverflow.com/questions/2652460/c-sharp-how-to-get-the-name-of-the-current-method-from-code var fn = new methods(); fn.reflection().Dump("reflection"); fn.stacktrace().Dump("stacktrace"); fn.inlineconstant().Dump("inlineconstant"); fn.constant().Dump("constant"); fn.expr().Dump("expr"); fn.exprmember().Dump("exprmember"); fn.callermember().Dump("callermember"); new Perf { { "reflection", n => fn.reflection() }, { "stacktrace", n => fn.stacktrace() }, { "inlineconstant", n => fn.inlineconstant() }, { "constant", n => fn.constant() }, { "expr", n => fn.expr() }, { "exprmember", n => fn.exprmember() }, { "callermember", n => fn.callermember() }, }.Vs("Method name retrieval"); } // Define other methods and classes here class methods { public string reflection() { return System.Reflection.MethodBase.GetCurrentMethod().Name; } public string stacktrace() { return new StackTrace().GetFrame(0).GetMethod().Name; } public string inlineconstant() { return "inlineconstant"; } const string CONSTANT_NAME = "constant"; public string constant() { return CONSTANT_NAME; } public string expr() { Expression<Func<methods, string>> ex = e => e.expr(); return ex.ToString(); } public string exprmember() { return expressionName<methods,string>(e => e.exprmember); } protected string expressionName<T,P>(Expression<Func<T,Func<P>>> action) { // https://stackoverflow.com/a/9015598/1037948 return ((((action.Body as UnaryExpression).Operand as MethodCallExpression).Object as ConstantExpression).Value as MethodInfo).Name; } public string callermember([CallerMemberName]string name = null) { return name; } } 

结果

reflectionreflection

stacktrace stacktrace

inlineconstant inlineconstant

常数不变

expr e => e.expr()

exprmember exprmember

来电者

 Method name retrieval: (reflection) vs (stacktrace) vs (inlineconstant) vs (constant) vs (expr) vs (exprmember) vs (callermember) 154673 ticks elapsed ( 15.4673 ms) - reflection 2588601 ticks elapsed (258.8601 ms) - stacktrace 1985 ticks elapsed ( 0.1985 ms) - inlineconstant 1385 ticks elapsed ( 0.1385 ms) - constant 1366706 ticks elapsed (136.6706 ms) - expr 775160 ticks elapsed ( 77.516 ms) - exprmember 2073 ticks elapsed ( 0.2073 ms) - callermember >> winner: constant 

请注意, exprcallermember方法不太“正确”。 在那里你可以看到一个相关评论的重复,reflection比stacktrace快了15倍。

这个怎么样:

 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 

我想你应该能够从创build一个StackTrace 。 或者,像@ edg和@ LarsMæhlum所说的那样 ,MethodBase。 GetCurrentMethod ()

简单的处理方法是:

 System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name; 

如果System.Reflection包含在using块中:

 MethodBase.GetCurrentMethod().DeclaringType.FullName + "." + MethodBase.GetCurrentMethod().Name; 

如果只需要方法的string名称,则可以使用expression式。 请参阅http://joelabrahamsson.com/entry/getting-property-and-method-names-using-static-reflection-in-c-sharp

尝试这个…

  /// <summary> /// Return the full name of method /// </summary> /// <param name="obj">Class that calls this method (use Report(this))</param> /// <returns></returns> public string Report(object obj) { var reflectedType = new StackTrace().GetFrame(1).GetMethod().ReflectedType; if (reflectedType == null) return null; var i = reflectedType.FullName; var ii = new StackTrace().GetFrame(1).GetMethod().Name; return string.Concat(i, ".", ii); } 

我只是用一个简单的静态类来做到这一点:

 using System.Runtime.CompilerServices; . . . public static class MyMethodName { public static string Show([CallerMemberName] string name = "") { return name; } } 

那么在你的代码中:

 private void button1_Click(object sender, EventArgs e) { textBox1.Text = MyMethodName.Show(); } private void button2_Click(object sender, EventArgs e) { textBox1.Text = MyMethodName.Show(); }