简体   繁体   中英

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?

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

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.

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.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM