tags:

views:

72

answers:

4

Hello guys,

can Log method of class A get to know who calls it ?

class A
{
    public void Log(string msg)
    {
        Log.Write("method_name: " + msg);
    }
}

I want to know a name of class and a name of a method.

+2  A: 

You can always step back in the call stack

David Hedlund
+1: this is really the best way to do it, but do watch out for the performance implications. I don't know exactly how bad the hit is, but you should definitely consider if you want to have this running in your release builds, especially if you call `Log` a lot.
Chris Schmich
+3  A: 

You can use the StackTrace and StackFrame classes. You can either get a whole stack trace by calling the StrackTrace constructor, or just a particular stack frame using the StackFrame constructor which takes the number of frames to skip.

You should be aware that it can be inaccurate due to inlining. (e..g method A inlines method B which calls your method - method A will be reported, not B).

Sample code:

using System;
using System.Diagnostics;

class Test
{
    static void ShowCaller()
    {
        // Use this code if you want multiple frames
        // StackTrace trace = new StackTrace();
        // StackFrame frame = trace.GetFrame(1);

        // Use this code if you're only interested in one frame
        StackFrame frame = new StackFrame(1);
        Console.WriteLine(frame.GetMethod());
    }

    static void Intermediate()
    {
        ShowCaller();
    }

    static void Main()
    {
        Intermediate();
    }
}

Running as an optimized release build, this will print Void Main() - when running a debug build, or if you put more code into the Intermediate() method, it will print Void Intermediate().

(As mentioned in comments, this will also create a performance hit. You should measure it to see if it's acceptable in your particular case.)

Jon Skeet
I've seen a logging method intentionally flagged as no-inline, precisely for this reason. But, as you said, there's significant overhead, so I wouldn't recommend that sort of thing.
Steven Sudit
(I mean [MethodImpl(MethodImplOptions.NoInlining)], to be specific.)
Steven Sudit
@Steven: But it wouldn't be the logging method in this case - it would be the method *calling* the logging method.
Jon Skeet
@Jon: Sorry, I wasn't clear. The code I saw had a private `Log` method with public methods to log with a particular severity code, such as `Fail`, `Warn`, etc. These public methods had the NoInlining attribute so that `Log` could look *two* callers back, whether in debug or release. I hope that clarifies things.
Steven Sudit
@Steve: Yup, that makes sense. It would still cause a problem if the code calling Fail or Warn was inlined though :)
Jon Skeet
@Jon: Yes, if `Foo` called a short `Bar` that logged with `Fail`, we might get `Foo` mentioned instead of `Bar`.
Steven Sudit
A: 

Yes, it can - by creating a new StackTrace object and then use stackTrace.GetFrame(1).GetMethod().Name - however, this is likely an expensive operation, so test and check that it doesn't cause undue slowdown of your application.

Will A
Log.Write is most likely not cheap so my comment re: expensiveness might be premature... :)
Will A
Maybe not. `Log.Write` *should* be as cheap as possible, since you want it to be usable for non-error logging as well. The usual way to make that possible is to have it return as quickly as it can, placing the log entry into a queue that is written by a single thread (potentially with lower priority).
Steven Sudit
A: 

you can also try:

 class staitc A
    {
        public staitc  void Log(string msg)
        {
            Log.Write("method_name: " + msg);
        }
    }


        using System.Reflection;

class TestClass
{
       // in method

        private void TestMethod()
    {
           A.Log(MethodBase.GetCurrentMethod().Name +MethodBase.GetCurrentMethod().DeclaringType.FullName);
    }
}
anishmarokey