views:

1836

answers:

5

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.

+3  A: 

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();
}
John Leidegren
John Leidgren - That will get me the name "PopularMethod", but I want the name of the method that called PopularMethod.
Scott Vercuski
Right, well the stack trace is what you need then. I misread your question.
John Leidegren
The just use .GetFrame(1) instead, right?
Andrew Backer
+1 for the `MethodInlining.NoInlining`. BTW the false on the StackTrace .ctor invocation is redundant, isnt it?
Ruben Bartelink
I believe it did exhibit slightly better preformance if I didn't ask for the file information explicitly. Truth be told, it probably doesn't matter, the main reason why I did it like that, was because I didn't need the file information.
John Leidegren
+12  A: 

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.

Jason
For more info see:http://discuss.joelonsoftware.com/default.asp?dotnet.12.511358.10
Eric Lathrop
System.Diagnostics is the namespace of StackTrace, System.Reflection is the namespace of MethodBase.
Guvante
Jason - Thank you, I'm not sure how resource intensive the "StackTrace" method is, but this does get me what I'm looking for. This is just a debugging code block for me, this won't be going into production. Thank you again for your help !
Scott Vercuski
This has code smell to me; maybe there's some issues with your OO design here that make you want to see who called your method. In that case maybe you've got a polymorphism break?
jcollum
@Scott Vercuski - It's an immensly expensive operation, if there's any way you can avoid this you really should. It way worse than throwing exceptions and that's bad. It's nice that it can be done, but it should not be misused.
John Leidegren
@John Leidegren - Definitely ... this isn't going into production code, we're just doing some massive QA testing and getting some strange happenings, this is just to help figure out where things are going haywire. Thank you !
Scott Vercuski
+2  A: 

Just pass in a prameter

public void PopularMethod(object sender)
{

}

If its good enough for events it should be good enough for this. IMO

Sruly
Sruly - Yes that is definitely an option, I was trying to do it without altering the method call. This would be my last resort option.
Scott Vercuski
Unless you are exposing this as a public API, why would you go through a hassle and use reflection if you can just do it this way? REmember KISS
Sruly
This is the BEST answer, do not use reflection or other stuff, ID the caller via a parameter.
Allen
A: 

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...)

C. Dragon 76
A: 

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.

BFree