C# 如何找到调用当前方法的方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/171970/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I find the method that called the current method?
提问by flipdoubt
When logging in C#, how can I learn the name of the method that called the current method? I know all about System.Reflection.MethodBase.GetCurrentMethod()
, but I want to go one step beneath this in the stack trace. I've considered parsing the stack trace, but I am hoping to find a cleaner more explicit way, something like Assembly.GetCallingAssembly()
but for methods.
登录C#时,如何得知调用当前方法的方法名?我知道所有关于System.Reflection.MethodBase.GetCurrentMethod()
,但我想在堆栈跟踪中更进一步。我已经考虑过解析堆栈跟踪,但我希望找到一种更清晰、更明确的方式,例如Assembly.GetCallingAssembly()
但是对于方法。
采纳答案by Firas Assaad
Try this:
尝试这个:
using System.Diagnostics;
// Get call stack
StackTrace stackTrace = new StackTrace();
// Get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
one-liner:
单线:
(new System.Diagnostics.StackTrace()).GetFrame(1).GetMethod().Name
It is from Get Calling Method using Reflection [C#].
回答by Lasse V. Karlsen
Note that doing so will be unreliable in release code, due to optimization. Additionally, running the application in sandbox mode (network share) won't allow you to grab the stack frame at all.
请注意,由于优化,这样做在发布代码中是不可靠的。此外,在沙箱模式(网络共享)下运行应用程序根本不允许您获取堆栈帧。
Consider aspect-oriented programming(AOP), like PostSharp, which instead of being called from your code, modifies your code, and thus knows where it is at all times.
回答by Yuval Peled
Take a look at Logging method name in .NET. Beware of using it in production code. StackFrame may not be reliable...
查看.NET中的Logging 方法名称。小心在生产代码中使用它。StackFrame 可能不可靠...
回答by Alex Lyman
In general, you can use the System.Diagnostics.StackTrace
class to get a System.Diagnostics.StackFrame
, and then use the GetMethod()
method to get a System.Reflection.MethodBase
object. However, there are some caveatsto this approach:
一般情况下,可以使用System.Diagnostics.StackTrace
类获取a System.Diagnostics.StackFrame
,然后使用GetMethod()
方法获取System.Reflection.MethodBase
对象。但是,这种方法有一些注意事项:
- It represents the runtimestack -- optimizations could inline a method, and you will notsee that method in the stack trace.
- It will notshow any native frames, so if there's even a chance your method is being called by a native method, this will notwork, and there is in-fact no currently available way to do it.
- 它代表运行时堆栈——优化可以内联一个方法,并且您不会在堆栈跟踪中看到该方法。
- 这将不显示任何本地帧,所以如果有甚至有机会你的方法是由一个本地方法调用,这将不工作,并且在-事实上目前没有做到这一点可用的方法。
(NOTE: I am just expanding on the answerprovided by Firas Assad.)
(注意:我只是在扩展Firas Assad 提供的答案。)
回答by Joel Coehoorn
We can improve on Mr Assad's code (the current accepted answer) just a little bit by instantiating only the frame we actually need rather than the entire stack:
我们可以通过仅实例化我们实际需要的框架而不是整个堆栈来稍微改进 Assad 先生的代码(当前接受的答案):
new StackFrame(1).GetMethod().Name;
This might perform a little better, though in all likelihood it still has to use the full stack to create that single frame. Also, it still has the same caveats that Alex Lyman pointed out (optimizer/native code might corrupt the results). Finally, you might want to check to be sure that new StackFrame(1)
or .GetFrame(1)
don't return null
, as unlikely as that possibility might seem.
这可能会表现得更好一点,但很可能它仍然必须使用完整的堆栈来创建单个帧。此外,它仍然具有与 Alex Lyman 指出的相同的警告(优化器/本机代码可能会破坏结果)。最后,您可能需要检查以确保new StackFrame(1)
或.GetFrame(1)
不返回null
,尽管这种可能性看起来不太可能。
See this related question: Can you use reflection to find the name of the currently executing method?
看到这个相关的问题: 你能用反射来查找当前正在执行的方法的名称吗?
回答by jesal
Maybe you are looking for something like this:
也许你正在寻找这样的东西:
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
回答by GregUzelac
Another approach I have used is to add a parameter to the method in question. For example, instead of void Foo()
, use void Foo(string context)
. Then pass in some unique string that indicates the calling context.
我使用的另一种方法是向相关方法添加一个参数。例如,代替void Foo()
,使用void Foo(string context)
。然后传入一些指示调用上下文的唯一字符串。
If you only need the caller/context for development, you can remove the param
before shipping.
如果您只需要调用者/上下文进行开发,您可以删除param
之前的运输。
回答by Flanders
/// <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;
}
回答by Tebo
private static MethodBase GetCallingMethod()
{
return new StackFrame(2, false).GetMethod();
}
private static Type GetCallingType()
{
return new StackFrame(2, false).GetMethod().DeclaringType;
}
A fantastic class is here: http://www.csharp411.com/c-get-calling-method/
一个很棒的课程在这里:http: //www.csharp411.com/c-get-calling-method/
回答by Coincoin
In C# 5 you can get that information using caller info:
在 C# 5 中,您可以使用caller info获取该信息:
//using System.Runtime.CompilerServices;
public void SendError(string Message, [CallerMemberName] string callerName = "")
{
Console.WriteLine(callerName + "called me.");
}
You can also get the [CallerFilePath]
and [CallerLineNumber]
.
您还可以获得[CallerFilePath]
和[CallerLineNumber]
。