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.
How about...
using System.Diagnostics;
// get call stack
StackTrace stackTrace = new StackTrace();
// get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
From here?
Note that doing so will be unreliable in release code, due to optimization. Additionally, running the app in sandbox mode (network share) won't allow you to grab the stack frame at all.
Have you considered AOP, like PostSharp, which instead of being called from your code, modifies your code, and thus knows where it is at all times?
Take a look at: http://www.codeproject.com/KB/dotnet/MethodName.aspx
Beware of using it in production code. StackFrame may not be reliable...
NOTE: Just expanding on the answer provided by Firas Assad
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 caveats to this approach:
- It represents the runtime stack -- optimizations could inline a method, and you will _**not**_ see that method in the stack trace.
- It will _**not**_ show any native frames, so if there's even a chance your method is being called by a native method, this will _**not**_ work, and there is in-fact no currently available way to do it.
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:
new StackFrame(1).GetMethod().Name;
This should perform a little better. However, it still has the same caveats that Alex Lyman pointed out. Also, 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.
See this related question: http://stackoverflow.com/questions/44153/can-you-use-reflection-to-find-the-name-of-the-currently-executing-method
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
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.
If you only need the caller/context for development, you can remove the param before shipping.
/// <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;
}