Getting the instance that called the method in C#

21,597

Solution 1

Obviously i don't know the exact details of your situation but this really seems like you need to rethink your structure a bit.

This could easily be done if proper inheritance is structured.

Consider looking into an abstract class and classes that inherit from said abstract class. You might even be able to accomplish the same thing with interfaces.

Solution 2

Here's an example of how to do this...

...
using System.Diagnostics;
...

public class MyClass
{
/*...*/
    //default level of two, will be 2 levels up from the GetCaller function.
    private static string GetCaller(int level = 2)
    {
        var m = new StackTrace().GetFrame(level).GetMethod();

        // .Name is the name only, .FullName includes the namespace
        var className = m.DeclaringType.FullName;

        //the method/function name you are looking for.
        var methodName = m.Name;

        //returns a composite of the namespace, class and method name.
        return className + "->" + methodName;
    }

    public void DoSomething() {
        //get the name of the class/method that called me.
        var whoCalledMe = GetCaller();
        //...
    }
/*...*/
}

Posting this, because it took me a while to find what I was looking for myself. I'm using it in some static logger methods...

Solution 3

You could get to the current stack trace in code and walk up one step. http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx

But as was commented below, this will get you the method and class calling you, but not the instance (if there is one, could be a static of course).

Share:
21,597
Willem Van Onsem
Author by

Willem Van Onsem

It's Willem, not William. Geek holiday calendar. A list of Django anti-patterns. The box said "Requires Windows 7 or better" so I installed Linux. You can buy me a coffee.

Updated on December 25, 2020

Comments

  • Willem Van Onsem
    Willem Van Onsem over 3 years

    I am looking for an algorithm that can get the object that called the method, within that method.

    For instance:

    public class Class1 {
    
        public void Method () {
            //the question
            object a = ...;//the object that called the method (in this case object1)
            //other instructions
        }
    
    }
    
    public class Class2 {
    
        public Class2 () {
            Class1 myClass1 = new Class1();
            myClass1.Method();
        }
    
        public static void Main () {
            Class2 object1 = new Class2();
            //...
        }
    
    }
    

    Is there any way to do this?

  • David Basarab
    David Basarab about 14 years
    The issue with this it will can give what called it. Not the instance of the object calling it.
  • jason
    jason about 14 years
    Encapsulation is a language feature enforced by the compiler. We can break it in all sorts of ways at runtime (for example, using reflection we can modify private fields).
  • T.J. Crowder
    T.J. Crowder about 14 years
    It's not impossible because it breaks encapsulation (lots of things that are possible do that). It's a very bad idea because of that. :-)
  • Morfildur
    Morfildur about 14 years
    Well, i'd rather say "Not possible" than explain "It's not a good idea, because..." and then getting the response "Yeah, yeah, i haven't listened to your stuff on bad style and whatever and my idea sounds cool so i will just do it".
  • jason
    jason about 14 years
    It doesn't matter what you'd rather say; your answer is premised on a factually incorrect statement.
  • Tracker1
    Tracker1 over 12 years
    I should note, that this won't work for your need, as you want the instance of the given object... in which case you should re-think.
  • Jon Barker
    Jon Barker about 10 years
    Run this in release mode and the compiler will optimize the callstack, which will cause you problems. In .NET 4.5 there's now the CallerMemberName attribute
  • Mike
    Mike over 9 years
    That's it! I really disapprove comments like @Lazarus made ('Why do you even need this') and even more that they are getting upvoted. I needed this for exactly same thing as you, static logger called by many threads.
  • Iucounu
    Iucounu almost 7 years
    a) It won't break encapsulation, any more than passing in an object to a method would. b) It's not impossible to know the type of the object. If you had a reference to it, you could simply call .GetType() . c) It would be easier. "Better" is a value judgment, which depends in part on design goals and requirements of an API. It would be better on speed to use a passed-in reference than engage in some sort of reflection, certainly.
  • DubiousPusher
    DubiousPusher about 6 years
    You may be wrong but thank you for actually answering the question.
  • Droa
    Droa almost 5 years
    this answer is really underrated, I was looking for a way to do some simple logging, without using NLog, Log4Net, etc. and I didn't know I could create a StackTrace, this solution helped me out.