Idov
Idov

Reputation: 5134

Detecting which object invoked the method in C#

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?

Upvotes: 1

Views: 430

Answers (4)

Marc Gravell
Marc Gravell

Reputation: 1064324

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)

Upvotes: 0

akton
akton

Reputation: 14386

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.

Upvotes: 1

LukeHennerley
LukeHennerley

Reputation: 6444

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);
   }
}

Upvotes: 1

PhonicUK
PhonicUK

Reputation: 13874

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.

Upvotes: 1

Related Questions