tags:

views:

232

answers:

5

Is there any way, in C#, for a class or method to know who (i.e. what class/ method) invoked it?

For example, I might have

class a{
   public void test(){
         b temp = new b();
         string output = temp.run();
   }
}

class b{
   public string run(){
        **CODE HERE**
   }
}

Output: "Invoked by the 'test' method of class 'a'."

+2  A: 

You can look at the stack trace to determine who called it.

http://msdn.microsoft.com/en-us/library/system.environment.stacktrace.aspx

Nippysaurus
StackTrace is not guaranteed to give you a complete stack trace, only an approximation. See the Remarks at http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx for more info. Also see http://www.hanselman.com/blog/ReleaseISNOTDebug64bitOptimizationsAndCMethodInliningInReleaseBuildCallStacks.aspx for examples of where the NoInlining attribute won't help you. The fact that certain optimizations occur in 64-bit and not 32-bit mode is an implementation detail of the JITter and is subject to change without warning.
Levi
Thats actually pretty interesting.I am assuming that the reason for needing to know which class called a function would only be for debugging, which this will likely be useful for. But yeah if this is used for application logic then its bad idea because of performance anyhow.
Nippysaurus
+1  A: 

You could create and examine examine a System.Diagnostics.StackTrace

Jonathan
+11  A: 

StackFrame

var frame = new StackFrame(1);

Console.WriteLine("Called by method '{0}' of class '{1}'",
    frame.GetMethod(),
    frame.GetMethod().DeclaringType.Name);
Jimmy
Yeah, this would seem to be exactly the solution. Just to clarify, `new StackFrame(1)` returns the stack frame at one level up from the current (active) frame.
Noldorin
Didn't know the nice overload ... +1
Daniel Brückner
A: 

The following expression will give you the calling method.

new StackTrace().GetFrame(1).GetMethod()

Daniel Brückner
A: 

StackFrame will do it, as Jimmy suggested. Beware when using StackFrame, however. Instantiating it is fairly costly, and depending on exactly where you instantiate it, you may need to specify MethodImplOptions.NoInlining. If you wish to wrap up the stack walk to find the callee's caller in a uttily function, you'll need to do this:

[MethodImpl(MethodImplOptions.NoInlining)]
public static MethodBase GetThisCaller()
{
    StackFrame frame = StackFrame(2); // Get caller of the method you want
                                      // the caller for, not the immediate caller
    MethodBase method = frame.GetMethod();
    return method;
}
jrista