Determine Calling Object Type in C#

First, yes, it's a terrible idea to do this and breaks all kinds of solid design principles. You should definitely consider an alternative approach if that's open, like simply using polymorphism—this seems like it can be refactored to a pretty clear case of single dispatch.

Secondly, yes, it's possible. Use System.Diagnostics.StackTrace to walk the stack; then get the appropriate StackFrame one level up. Then determine which method was the caller by using GetMethod() on that StackFrame. Note that building a stack trace is a potentially expensive operation, and it's possible for callers of your method to obscure where things are really coming from.


Edit: This comment from the OP makes it pretty clear that this could probably be a generic or polymorphic method. @devinb, you might want to consider making a new question that provides more detail about what you're trying to do, and we can see if it lends itself well to a good solution.

The short version is that I would end up have 30 or 40 identical functions that were simply off by one or two lines. – devinb (12 secs ago)


As an alternative approach, have you ever considered offering up a different class based on the type of the object that is asking for the class. Say the following

public interface IC {
  int DoSomething();
}

public static CFactory { 
  public IC GetC(Type requestingType) { 
    if ( requestingType == typeof(BadType1) ) { 
      return new CForBadType1();
    } else if ( requestingType == typeof(OtherType) { 
      return new CForOtherType();
    }  
    ...
  }
}

This would be a much cleaner approach than have each method change it's behavior based on the calling object. It would cleanly separate out the concerns to the different implementations of IC. Additionally, they could all proxy back to the real C implementation.

EDIT Examining the callstack

As several other people pointed out you can examine the callstack to determine what object is immediately calling the function. However this is not a foolproof way to determine if one of the objects you want to special case is calling you. For instance I could do the following to call you from SomeBadObject but make it very difficult for you to determine that I did so.

public class SomeBadObject {
  public void CallCIndirectly(C obj) { 
    var ret = Helper.CallDoSomething(c);
  }
}

public static class Helper {
  public int CallDoSomething(C obj) {
    return obj.DoSomething();
  }
}

You could of course walk further back on the call stack. But that's even more fragile because it may be a completely legal path for SomeBadObject to be on the stack when a different object calls DoSomething().


Starting with Visual Studio 2012 (.NET Framework 4.5) you can automatically pass caller information to a method by using caller attributes (VB and C#).

public void TheCaller()
{
    SomeMethod();
}

public void SomeMethod([CallerMemberName] string memberName = "")
{
    Console.WriteLine(memberName); // ==> "TheCaller"
}

The caller attributes are in the System.Runtime.CompilerServices namespace.


This is ideal for the implementation of INotifyPropertyChanged:

private void OnPropertyChanged([CallerMemberName]string caller = null) {
     var handler = PropertyChanged;
     if (handler != null) {
        handler(this, new PropertyChangedEventArgs(caller));
     }
}

Example:

private string _name;
public string Name
{
    get { return _name; }
    set
    {
        if (value != _name) {
            _name = value;
            OnPropertyChanged(); // Call without the optional parameter!
        }
    }
}

Tags:

C#

Types