检测c#中哪个对象调用了该方法

本文关键字:调用 方法 对象 检测 | 更新日期: 2023-09-27 17:50:29

在c#中是否有一种方法来检测哪个对象调用了一个方法?
例如:

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.
  }
}

是否有可能知道在Foo2::做,它是从Foo1调用?

检测c#中哪个对象调用了该方法

正确的方法是修改do的签名:

void Do(object sender)

调用时:

m_inner.Do(this);

否则你将使用调用堆栈和一些反射

你为什么不能像使用事件一样使用发送者对象呢?

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

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

有三种处理方法。第一个是传递给方法的发送方对象,就像. net事件中包含的那样。这以一种非常明显的方式将发送方暴露给调用方,并允许该方法回调发送方。但是,如果代码对安全性敏感(例如,确保该方法只能从库X调用),则不适合这样做。

第二种方法是System.Diagnostics.StackTrace类。看我如何得到当前的行号?举个例子。您可以从元数据中检查调用类型和程序集。

如果您不介意为方法添加可选参数,第三种方法是使用CallerMemberName和CallerFilePath属性。然而,这可能不是您想要的。然而,与StackTrace方法不同,这是通过混淆实现的。

我添加这一点是为了完整性,但请注意,它在构造函数的情况下没有有多大帮助,因为调用者的方法名称将始终是.ctor;但是:

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

现在,像这样的调用:

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

"SomeMethod"作为caller传入。正如我提到的,它不能很好地用于构造函数,构造函数提供了两个选项:

  • 显式传递名称;someObj.Do("SyntheticNameHere");
  • 添加一个恰当命名的本地方法,调用Do(似乎有点夸张)