关于.net:您可以使用反射来查找当前正在执行的方法的名称吗?

关于.net:您可以使用反射来查找当前正在执行的方法的名称吗?

Can you use reflection to find the name of the currently executing method?

正如标题所说:"可以反射给您当前执行方法的名称。"

因为海森堡的问题,我倾向于不这样认为。如何在不更改当前方法的情况下调用一个方法来告诉您当前方法?但我希望有人能证明我错了。

更新:

  • 第2部分:这是否也可以用于查找属性的内部代码?
  • 第三部分:表演会是怎样的?

最终结果我了解了methodBase.getCurrentMethod()。我还了解到,我不仅可以创建一个堆栈跟踪,而且如果需要,我只能创建所需的确切帧。

要在属性中使用此函数,只需使用.substring(4)删除"set_uu"或"get_uu"。


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

http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.getcurrentmethod.aspx


从.NET 4.5开始,您还可以使用[CallerMemberName]

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

1
2
3
4
5
6
7
8
9
10
    protected void SetProperty<T>(T value, [CallerMemberName] string property = null)
    {
        this.propertyValues[property] = value;
        OnPropertyChanged(property);
    }

    public string SomeProperty
    {
        set { SetProperty(value); }
    }

编译器将在调用站点提供匹配的字符串文本,因此基本上没有性能开销。


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

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

这应该将相同的结果返回给methodBase.getcurrentMethod().name技术,但它仍然值得指出,因为我可以在它自己的方法中使用上一个方法的索引1实现这一点,并从许多不同的属性调用它。此外,它只返回一帧,而不是整个堆栈跟踪:

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

这也是一条单行线;)


在空控制台程序的主方法中尝试此操作:

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

控制台输出:Main


是的。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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;
}

这条线:

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

在堆栈框架中查找调用方法,然后使用反射获取传递给它的通用错误报告函数的参数信息值。要获取当前方法,只需使用当前堆栈帧(1)。

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

1
MethodBase.GetCurrentMethod()

我更喜欢遍历堆栈,因为如果从内部看这个方法,它只会创建一个StackCrawlMark。对我来说,直接寻址堆栈似乎更清晰

post 4.5现在您可以使用[callermembernameattribute]作为方法参数的一部分来获取方法名称的字符串-这在某些情况下可能会有所帮助(但实际上在上面的示例中)。

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

这似乎主要是一个针对inotifyPropertiesChanged支持的解决方案,以前在事件代码中到处都是字符串。


比较获取方法名的方法--在LinqPad中使用任意计时构造:

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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;
    }
}

结果

反射反射

堆栈跟踪堆栈跟踪

内联常数内联常数

常数常数

EXPRE= > EXPRE()

Exp成员Exp成员

来电会员主要的

1
2
3
4
5
6
7
8
9
10
11
12
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方法并不完全"正确"。在这里,您可以看到重复的相关注释,反射比stacktrace快约15倍。


edit:methodbase可能是获取您所在方法的更好方法(而不是整个调用堆栈)。不过,我还是担心内线。

您可以在以下方法中使用stacktrace:

1
StackTrace st = new StackTrace(true);

看看这些框架:

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

但是,请注意,如果方法是内联的,那么您将不在您认为自己在方法中。可以使用属性来防止内联:

1
[MethodImpl(MethodImplOptions.NoInlining)]

简单的处理方法是:

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

如果system.reflection包含在using块中:

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

这个怎么样:

1
2
3
4
5
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

我认为您应该能够从创建stacktrace中得到它。或者,作为@edg和@lars m?hlum提述,methodbase.getcurrentmethod()


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

1
2
3
4
5
6
7
8
9
10
11
using System.Runtime.CompilerServices;
.
.
.
    public static class MyMethodName
        {
            public static string Show([CallerMemberName] string name ="")
            {
                return name;
            }
        }

然后在您的代码中:

1
2
3
4
5
6
7
8
9
private void button1_Click(object sender, EventArgs e)
        {
            textBox1.Text = MyMethodName.Show();
        }

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


试试这个…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    /// <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);
    }

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


推荐阅读

    linux命令行执行py?

    linux命令行执行py?,系统,环境,官网,一致,文件,程序,脚本,源文件,后台,终端,l

    linux命令查找内容?

    linux命令查找内容?,命令,文件,网络,名称,信息,工作,标准,系统,管理,位置,lin

    linux脚步中执行命令?

    linux脚步中执行命令?,工具,代码,命令,名称,系统,连续,环境,发行,文件,终端,l

    linux执行权限命令行?

    linux执行权限命令行?,地址,电脑,系统,数字,工作,权限,目录,文件,新增,信息,L

    程序执行linux命令?

    程序执行linux命令?,系统,工作,地址,环境,信息,管理,命令,文件,目录,程序,lin

    linux执行2个命令?

    linux执行2个命令?,工作,系统,基础,命令,基础知识,信息,管理,在线,概念,第一

    调用函数命令linux?

    调用函数命令linux?,系统,管理,网络,通用,统一,观察,地址,代码,设备,地方,怎

    linux查找包的命令?

    linux查找包的命令?,基础,软件,项目,数据,名称,命令,环境,技术,文件,子目录,

    linux命令批量执行?

    linux命令批量执行?,系统,代码,工作,周期性,数据,定期,环境,命令,文件,脚本,l

    linux二进制执行命令?

    linux二进制执行命令?,系统,工作,情况,代码,信息,位置,地址,命令,文件,目录,L

    linux执行退出命令?

    linux执行退出命令?,档案,状态,工作,命令,信息,地址,电脑,系统,编辑,文件,lin

    linux中后台执行命令?

    linux中后台执行命令?,系统,状态,暂停,灵活,电脑,网络,服务,第一,名字,命令,l

    linux常用的执行命令?

    linux常用的执行命令?,系统,地址,工作,基础,标准,命令,工具,环境,信息,代码,L

    linux执行线程命令?

    linux执行线程命令?,系统,工作,线程,软件,服务,管理,信息,环境,名称,命令,lin

    linux执行多条命令?

    linux执行多条命令?,数据,通信,管理,系统,命令,标准,信息,工具,代码,环境,Lin

    linux内核总调用命令?

    linux内核总调用命令?,工作,地址,系统,信息,管理,策略,命令,目录,时间,基础,

    linux编程调用命令?

    linux编程调用命令?,系统,标准,管理,工作,基础知识,情况,环境,设备,基础,首

    linux命令查找字符串?

    linux命令查找字符串?,工具,信息,命令,字符串,系统,工作,文件,范本,样式,文

    linux退出命令未执行?

    linux退出命令未执行?,服务,工具,代码,环境,数据,官网,命令,用户,脚本,字符

    linux动态执行命令?

    linux动态执行命令?,时间,信息,名字,工作,网上,业务,工具,对比,地址,下来,如