1

Is there a way in C# to detect which object invoked a method?
for example:

class Foo1
{
   Foo2 m_inner = null
   Foo1()
   {
       m_inner = new Foo2();
       m_inner.Do();
   }
}


class Foo2
{
  Foo2()
  {
  }
  void Do()
  {
     //Here I want to know that Foo1 called it.
  }
}

IS it possible to know in Foo2::Do that it was called from Foo1?

Idov
  • 5,006
  • 17
  • 69
  • 106
  • 5
    Get the stacktrace. See http://stackoverflow.com/questions/531695/how-to-print-the-current-stack-trace-in-net-without-any-exception for examples. – ken2k Jan 02 '13 at 13:01
  • The stack trace can tell you if it was _a_ `Foo1` that called it but not *which* `Foo1` called it. If you need the latter you have to pass it as a parameter. – Alex Jan 02 '13 at 13:07
  • In c# 5, u can use [*caller info attributes*](http://msdn.microsoft.com/en-us/library/hh534540.aspx) – SekaiCode Jan 02 '13 at 13:12

4 Answers4

1

Any reason you can't use a sender object, similarly to an event?

class Foo2
{
  Foo2() {}
  void Do(object sender)
  {
    if(sender is Foo1)
      Console.Writeline("Sent from Foo1");
  }
}

Usage

class Foo1
{
   Foo2 m_inner = null
   Foo1()
   {
       m_inner = new Foo2();
       m_inner.Do(this);
   }
}
Roger Lipscombe
  • 89,048
  • 55
  • 235
  • 380
LukeHennerley
  • 6,344
  • 1
  • 32
  • 50
1

The 'proper' way to do this would to be to alter the signature of Do:

void Do(object sender)

Then when called:

m_inner.Do(this);

Otherwise you're going to be using the call stack and some reflection.

PhonicUK
  • 13,486
  • 4
  • 43
  • 62
1

There are three ways to handle this. The first is a sender object passed to the method, like that included with .Net events. This exposes the sender to the caller in a very obvious way and allows the method to call back to the sender. However, if the code is security sensitive (for example, ensure this method is only called from library X), this is not suitable.

The second way is the System.Diagnostics.StackTrace class. See See How do I get the current line number? for an example of its use. You can examine the calling type and assembly from the metadata.

The third, if you do not mind adding optional arguments to the method, is using the CallerMemberName and CallerFilePath attributes. However, this is probably not what you want here. This works through obfuscation, unlike the StackTrace method, however.

Community
  • 1
  • 1
akton
  • 14,148
  • 3
  • 43
  • 47
0

I'm adding this for completeness, but note that it does not help much in the case of a constructor, as the caller's method-name will always be .ctor; but:

public void Do([CallerMemberName] string caller = null)
{
    Console.WriteLine(caller);
}

Now, a call like:

void SomeMethod() {
    someObj.Do();
}

will pass in "SomeMethod" as caller. As I mention, it doesn't work as well for constructors, which gives you two options:

  • pass in the name explicitly; someObj.Do("SyntheticNameHere");
  • add a well-named local method named appropriately that calls Do (seems overkill)
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900