Retrieving the calling method name from within a method
C#ReflectionMethodsCalling ConventionC# Problem Overview
I have a method in an object that is called from a number of places within the object. Is there a quick and easy way to get the name of the method that called this popular method.
Pseudo Code EXAMPLE:
public Main()
{
PopularMethod();
}
public ButtonClick(object sender, EventArgs e)
{
PopularMethod();
}
public Button2Click(object sender, EventArgs e)
{
PopularMethod();
}
public void PopularMethod()
{
//Get calling method name
}
Within PopularMethod()
I would like to see the value of Main
if it was called from Main
... I'd like to see "ButtonClick
" if PopularMethod()
was called from ButtonClick
I was looking at the System.Reflection.MethodBase.GetCurrentMethod()
but that won't get me the calling method. I've looked at the StackTrace
class but I really didn't relish running an entire stack trace every time that method is called.
C# Solutions
Solution 1 - C#
In .NET 4.5 / C# 5, this is simple:
public void PopularMethod([CallerMemberName] string caller = null)
{
// look at caller
}
The compiler adds the caller's name automatically; so:
void Foo() {
PopularMethod();
}
will pass in "Foo"
.
Solution 2 - C#
I don't think it can be done without tracing the stack. However, it's fairly simple to do that:
StackTrace stackTrace = new StackTrace();
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod();
Console.WriteLine(methodBase.Name); // e.g.
However, I think you really have to stop and ask yourself if this is necessary.
Solution 3 - C#
This is actually really simple.
public void PopularMethod()
{
var currentMethod = System.Reflection.MethodInfo
.GetCurrentMethod(); // as MethodBase
}
But be careful through, I'm a bit skeptical to if inlining the method has any effect. You can do this to make sure that the JIT compiler won't get in the way.
[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public void PopularMethod()
{
var currentMethod = System.Reflection.MethodInfo
.GetCurrentMethod();
}
To get the calling method:
[System.Runtime.CompilerServices.MethodImpl(
System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
public void PopularMethod()
{
// 1 == skip frames, false = no file info
var callingMethod = new System.Diagnostics.StackTrace(1, false)
.GetFrame(0).GetMethod();
}
Solution 4 - C#
Just pass in a parameter
public void PopularMethod(object sender)
{
}
IMO: If it's good enough for events it should be good enough for this.
Solution 5 - C#
I have often found my self wanting to do this, but have always ending up refactoring the design of my system so I don't get this "Tail wagging the dog" anti-pattern. The result has always been a more robust architecture.
Solution 6 - C#
While you can most definitley trace the Stack and figure it out that way, I would urge you to rethink your design. If your method needs to know about some sort of "state", I would say just create an enum or something, and take that as a Parameter to your PopularMethod(). Something along those lines. Based on what you're posting, tracing the stack would be overkill IMO.
Solution 7 - C#
I think you do need to use the StackTrace
class and then StackFrame.GetMethod()
on the next frame.
This seems like a strange thing to use Reflection
for though. If you are defining PopularMethod
, can't go define a parameter or something to pass the information you really want. (Or put in on a base class or something...)