登录C#时,如何得知调用当前方法的方法的名称? 我知道有关System.Reflection.MethodBase.GetCurrentMethod()全部知识,但是我想在堆栈跟踪中比这低一级。 我已经考虑过解析堆栈跟踪,但是我希望找到一种更清晰,更明确的方式,类似于Assembly.GetCallingAssembly()但用于方法。


#1楼

您可以使用“呼叫者信息”和可选参数:

public static string WhoseThere([CallerMemberName] string memberName = "")
{return memberName;
}

该测试说明了这一点:

[Test]
public void Should_get_name_of_calling_method()
{var methodName = CachingHelpers.WhoseThere();Assert.That(methodName, Is.EqualTo("Should_get_name_of_calling_method"));
}

尽管StackTrace可以在上面快速运行,并且在大多数情况下不会成为性能问题,但呼叫者信息仍然要快得多。 在1000次迭代的示例中,我将其速度提高了40倍。


#2楼

StackFrame caller = (new System.Diagnostics.StackTrace()).GetFrame(1);
string methodName = caller.GetMethod().Name;

我认为就足够了。


#3楼

我们也可以使用lambda来查找调用者。

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

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内部,我们现在可以调用上面定义的帮助器函数,并找到调用者方法的MethodInfo。

例:

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

#4楼

尝试这个:

using System.Diagnostics;
// Get call stack
StackTrace stackTrace = new StackTrace();// Get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);

它来自使用反射[C#]的Get调用方法


#5楼

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

考虑一下像PostSharp这样的面向方面的编程 (AOP),而不是从代码中调用它,而是修改您的代码,从而始终知道它在哪里。


#6楼

看看.NET中的Logging方法名称 。 当心在生产代码中使用它。 StackFrame可能不可靠...


#7楼

通常,可以使用System.Diagnostics.StackTrace类获取System.Diagnostics.StackFrame ,然后使用GetMethod()方法获取System.Reflection.MethodBase对象。 但是,此方法有一些警告 :

  1. 它代表运行时堆栈-优化可以内联一个方法,并且您不会在堆栈跟踪中看到该方法。
  2. 不会显示任何本机框架,因此,即使有可能您的方法被本机方法调用,也将无法正常工作,并且实际上目前尚无可用的方法。

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


#8楼

通过仅实例化我们实际需要的框架而不是整个堆栈,我们可以对阿萨德先生的代码(当前接受的答案)进行一些改进:

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

这可能会更好一些,尽管很可能仍然必须使用完整的堆栈来创建单个帧。 而且,它仍然具有Alex Lyman指出的警告(优化器/本地代码可能会破坏结果)。 最后,您可能需要检查以确保new StackFrame(1).GetFrame(1)不会返回null ,这似乎不太可能。

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


#9楼

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

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

#10楼

我使用的另一种方法是向有问题的方法添加参数。 例如,使用void Foo(string context)代替void Foo() void Foo(string context) 。 然后传递一些表示调用上下文的唯一字符串。

如果只需要调用者/上下文进行开发,则可以在发货前删除该param


#11楼

/// <summary>
/// Returns the call that occurred just before the "GetCallingMethod".
/// </summary>
public static string GetCallingMethod()
{return GetCallingMethod("GetCallingMethod");
}/// <summary>
/// Returns the call that occurred just before the the method specified.
/// </summary>
/// <param name="MethodAfter">The named method to see what happened just before it was called. (case sensitive)</param>
/// <returns>The method name.</returns>
public static string GetCallingMethod(string MethodAfter)
{string str = "";try{StackTrace st = new StackTrace();StackFrame[] frames = st.GetFrames();for (int i = 0; i < st.FrameCount - 1; i++){if (frames[i].GetMethod().Name.Equals(MethodAfter)){if (!frames[i + 1].GetMethod().Name.Equals(MethodAfter)) // ignores overloaded methods.{str = frames[i + 1].GetMethod().ReflectedType.FullName + "." + frames[i + 1].GetMethod().Name;break;}}}}catch (Exception) { ; }return str;
}

#12楼

var callingMethod = new StackFrame(1, true).GetMethod();
string source = callingMethod.ReflectedType.FullName + ": " + callingMethod.Name;

#13楼

从.NET 4.5开始,您可以使用“ 呼叫者信息”属性:

  • CallerFilePath调用函数的源文件;
  • CallerLineNumber调用该函数的代码行;
  • CallerMemberName调用该函数的成员。

     public void WriteLine( [CallerFilePath] string callerFilePath = "", [CallerLineNumber] long callerLineNumber = 0, [CallerMemberName] string callerMember= "") { Debug.WriteLine( "Caller File Path: {0}, Caller Line Number: {1}, Caller Member: {2}", callerFilePath, callerLineNumber, callerMember); } 

“ .NET Core”和“ .NET Standard”中也存在此功能。

参考文献

  1. Microsoft-呼叫者信息(C#)
  2. Microsoft- CallerFilePathAttribute
  3. Microsoft- CallerLineNumberAttribute
  4. Microsoft- CallerMemberNameAttribute

#14楼

快速回顾两种方法,速度比较是重要的部分。

http://geekswithblogs.net/BlackRabbitCoder/archive/2013/07/25/c.net-little-wonders-getting-caller-information.aspx

在编译时确定调用方

static void Log(object message,
[CallerMemberName] string memberName = "",
[CallerFilePath] string fileName = "",
[CallerLineNumber] int lineNumber = 0)
{// we'll just use a simple Console write for now    Console.WriteLine("{0}({1}):{2} - {3}", fileName, lineNumber, memberName, message);
}

使用堆栈确定调用方

static void Log(object message)
{// frame 1, true for source infoStackFrame frame = new StackFrame(1, true);var method = frame.GetMethod();var fileName = frame.GetFileName();var lineNumber = frame.GetFileLineNumber();// we'll just use a simple Console write for now    Console.WriteLine("{0}({1}):{2} - {3}", fileName, lineNumber, method.Name, message);
}

两种方法的比较

Time for 1,000,000 iterations with Attributes: 196 ms
Time for 1,000,000 iterations with StackTrace: 5096 ms

因此,您可以看到,使用属性快得多! 实际上快了将近25倍。


#15楼

显然,这是一个较晚的答案,但是如果您可以使用.NET 4.5或更高版本,那么我有一个更好的选择:

internal static void WriteInformation<T>(string text, [CallerMemberName]string method = "")
{Console.WriteLine(DateTime.Now.ToString() + " => " + typeof(T).FullName + "." + method + ": " + text);
}

这将打印当前的日期和时间,后跟“ Namespace.ClassName.MethodName”,并以“:text”结尾。
样本输出:

6/17/2016 12:41:49 PM => WpfApplication.MainWindow..ctor: MainWindow initialized

样品使用:

Logger.WriteInformation<MainWindow>("MainWindow initialized");

#16楼

private static MethodBase GetCallingMethod()
{return new StackFrame(2, false).GetMethod();
}private static Type GetCallingType()
{return new StackFrame(2, false).GetMethod().DeclaringType;
}

一个很棒的课程在这里: http : //www.csharp411.com/c-get-calling-method/


#17楼

要获取方法名称和类名称,请尝试以下操作:

    public static void Call(){StackTrace stackTrace = new StackTrace();var methodName = stackTrace.GetFrame(1).GetMethod();var className = methodName.DeclaringType.Name.ToString();Console.WriteLine(methodName.Name + "*****" + className );}

#18楼

有关Firas Assaad答案的更多信息。

我已经使用了new StackFrame(1).GetMethod().Name; 在具有依赖项注入的.net core 2.1中,我将调用方法称为“开始”。

我尝试使用[System.Runtime.CompilerServices.CallerMemberName] string callerName = "" ,它为我提供了正确的调用方法


#19楼

在C#5中,您可以使用调用方信息获取该信息:

//using System.Runtime.CompilerServices;
public void SendError(string Message, [CallerMemberName] string callerName = "")
{ Console.WriteLine(callerName + "called me.");
}

您还可以获取[CallerFilePath][CallerLineNumber]

如何找到调用当前方法的方法?相关推荐

  1. eclipse java调用c 代码吗_linux下通过eclipse开发用java调用c程序的方法

    linux下通过eclipse开发用java调用c程序的方法: 1.先建立好java工程并建立java文件如下: public class testso {     static {         ...

  2. 窗体调用 OCX 的使用方法(MFC,WINFORM)

    在上一篇中,我们做了一个OCX控件,叫mfcActive.ocx,在这一篇我们要做的就是使用这个ocx控件. 第一步:创建一个MFC的对话框工程(其实winform 也是一样的) 第二步:在工具箱中常 ...

  3. 举例讲解Linux系统下Python调用系统Shell的方法

    http://www.jb51.net/article/74508.htm 有时候难免需要直接调用Shell命令来完成一些比较简单的操作,比如mount一个文件系统之类的.那么我们使用Python如何 ...

  4. 织梦php调用字段,织梦dedecms搜索页调用自定义字段的方法

    这篇文章主要为大家详细介绍了织梦dedecms搜索页调用自定义字段的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,有需要的朋友可以收藏方便以后借鉴. 织梦dedecms搜索页调用自定义字段的 ...

  5. 安卓一个方法多处调用_一个隐藏在方法集和方法调用中且易被忽略的小细节

    来自公众号:新世界杂货铺 作为一个长期从事Go语言开发的程序猿,笔者不敢说自己是老油条但也勉强算一个小油条.然而就在今天,笔者研究TLS/SSL握手源码的时候,突然灵光一闪,想到了一个和自己认知不符的 ...

  6. c调用其他类的方法_Java 的 Native 方法——今天又进步了

    1. 简介 1.1 个人理解 初次遇见 native 是在 java.lang.String 源码中的一个 intern 方法: public native String intern(); 因为还是 ...

  7. html 动态调用php文件,html静态页面调用php文件的方法

    html静态页面调用php文件的方法 本文实例讲述了html静态页面调用php文件的方法.分享给大家供大家参考.具体方法如下: 静态页面中看上去好像是不能直接调用php文件的,但是却可以使用js调用方 ...

  8. php调用C代码的方法详解和zend_parse_parameters函数详解

    来源:http://my.oschina.net/Customs/blog/490873 http://blog.csdn.net/super_ufo/article/details/3863731 ...

  9. c调用python脚本如何获取结果_使用C++调用Python代码的方法详解

    一.配置python环境问题 1.首先安装Python(版本无所谓),安装的时候选的添加python路径到环境变量中 安装之后的文件夹如下所示: 2.在VS中配置环境和库 右击项目->属性-&g ...

最新文章

  1. pl/sql 报ORA-12154: TNS:无法解析指定的连接标志符
  2. node.js + express 初体验【hello world】
  3. /boot 目录文件丢失修复记录
  4. CNNIC报告:中国网民超8亿,人工智能取得突出成果
  5. carbon 一天的开始 结束_来自一线:银行柜员的一天
  6. 2017年美国大学生数学建模竞赛E题O奖65123论文解读
  7. VS2012下MFC程序的换肤(Skin++、SkinMagic、USkin、SkinSharp)
  8. Jmeter基础教程
  9. PHP之AJAX、POST传值【顶、踩】
  10. NOI题库 小学奥数
  11. latex如何实现单元格内文字的换行
  12. 解决eclipse在安装时工作空间出错问题的有效方法
  13. 洛阳九县八取名字_洛阳市地图(洛阳市九县六区地图)
  14. 解决:java.lang.UnsupportedClassVersionError
  15. 调整Android音量等级及默认音量
  16. cmake的-G 参数
  17. 图卷积在语义分割上的应用(论文集)
  18. java 必须是数字_[Java教程]限制只能输入数字
  19. mysql主键设置了递增,插入语句的写法
  20. MyBatis基本工作原理

热门文章

  1. 注册服务(addService)
  2. VC6.0 中的默认操作系统版本的问题
  3. 算法----删除链表中的节点(Java)
  4. 关于MySQL事务和存储引擎10个FAQ(Frequently asked questions
  5. 有关线程的相关知识(上)
  6. Android之记录并研究Volley框架中知识点
  7. Hive Lateral View、视图、索引
  8. iOS 绘制圆角矩形
  9. 大连理工大学计算机原理实验交通灯,大连理工大学计算机原理第四次实验.docx...
  10. java8新特性学习笔记链接