【问题标题】:Is there any way to get a reference to the calling object in c#?有没有办法在 c# 中获取对调用对象的引用?
【发布时间】:2009-01-07 14:43:37
【问题描述】:

我想知道的是是否有可能(例如)遍历堆栈帧,检查每个调用对象以查看是否与接口匹配,如果匹配则从中提取一些数据。

是的,我知道这是不好的做法,我想知道这是否可能。

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    不,没有 - 至少在不使用某种描述的分析/调试 API 的情况下不会。您可以遍历堆栈以找到调用 方法,但需要注意的是它真的很慢并且由于 JIT 优化可能不准确。这不会告诉你调用 object 是什么(如果确实有的话)。

    【讨论】:

    • Aaaah - 所以大概 VS 通过检测代码以某种复杂的方式完成它?
    • 好吧,不是通过检测代码,而是运行调试器 API 来提供各种信息 - 当然是有代价的。
    • 哦 - 我在哪里可以找到有关这些调试器 API 的更多信息?
    • andrewducker:老实说,我只是通过 Google 搜索来找出答案,所以我会让你这样做 :) 我从未使用过调试器/分析器 API - 鉴于它们用于低级的东西,我预计它们可能会很痛苦。
    • 所以这让我用了一些试图过于聪明的日志记录代码,检查 StackTrace 并向上帧以获取调用方法的名称。您可以通过在 Debug 模式下的简单计数来做到这一点,但在 Release 模式下,一些方法会被优化掉。一个很好的提示!
    【解决方案2】:

    如果你想得到类型你可以试试这个:

    new StackFrame(1).GetMethod().DeclaringType

    正如 Jon 指出的那样,如果您遇到 JIT 优化可能会出现问题。

    至于从对象中获取数据,我认为是不可能的。

    编辑

    只是为了详细说明优化问题,取以下代码:

    class stackTest
    {
        public void Test()
        {
            StackFrame sFrame = new StackFrame(1);
            if (sFrame == null)
            {
                Console.WriteLine("sFrame is null");
                return;
            }
    
            var method = sFrame.GetMethod();
    
            if (method == null)
            {
                Console.WriteLine("method is null");
                return;
            }
            Type declaringType = method.DeclaringType;
            Console.WriteLine(declaringType.Name);
        }
    
        public void Test2()
        {
            Console.WriteLine(new StackFrame(1).GetMethod().DeclaringType.Name);
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
    
            stackTest s = new stackTest();
            s.Test();
            Console.WriteLine("Doing Test2");
            s.Test2();
            Console.ReadLine();
    
        }
    }
    

    我们应该两次让 Program 进入控制台,当你在调试器中运行时,你会这样做。当您在发布模式下不使用调试器运行时,您会从第一个 Test 函数获得输出。这可能是因为内联太复杂了,但是,第二种方法会导致空引用异常。

    此代码的另一个危险是,在 MS 改进了 JIT 编译器,可能在 2.0 中工作的内容可能会在未来的版本中崩溃和烧毁。

    【讨论】:

      【解决方案3】:

      看到这个问题:
      Can you use reflection to find the name of the currently executing method?

      这不是重复的,但该问题的答案也会回答您的问题。

      【讨论】:

      • 并非如此 - 因为虽然获取调用方法是可行的,但这并不能告诉您进行调用的对象的实际类型。例如,它可能在 BaseClass.Foo() 中,但来自 DerivedClass 的实例,该实例实现了 Andrew 正在寻找的接口。
      • 它确实为您提供了堆栈跟踪。
      猜你喜欢
      • 1970-01-01
      • 2017-06-02
      • 1970-01-01
      • 1970-01-01
      • 2011-06-19
      • 2020-10-23
      • 2021-07-05
      • 1970-01-01
      • 2010-11-14
      相关资源
      最近更新 更多