代码之家  ›  专栏  ›  技术社区  ›  Dario

如何通过堆栈跟踪访问局部变量(模拟动态范围)

  •  7
  • Dario  · 技术社区  · 16 年前

    即使可以在运行时编译C#代码,也不可能在当前范围中包含并运行生成的代码。相反,所有变量都必须作为显式参数传递。

    与Python等动态编程语言相比,我们永远无法真正复制 eval (如本例所示)。

    x = 42
    print(eval("x + 1")) # Prints 43
    

    问题

    动态范围 在.NET中通过使用 .

    因为.NET为我们提供了 Diagnostics.StackTrace (如何)能够可靠地访问调用方法的局部变量

    堆栈跟踪是否为我们提供了足够的信息来计算内存偏移量,或者托管代码中是否禁止这样的事情?

    这样的代码有可能吗?

    void Foo() {
       int x = 42;
       Console.WriteLine(Bar());
    }
    
    int Bar() {
       return (int)(DynamicScope.Resolve("x")); // Will access Foo's x = 42
    }
    
    2 回复  |  直到 16 年前
        1
  •  5
  •   Tomas Petricek    16 年前

    这是不可能的。在编译的.NET代码(中间语言)中,变量仅表示为堆栈上的索引。例如 the ldloc instruction ,它加载变量的值只需要 unsigned int16 值作为参数。对于在调试模式下编译的应用程序,可能有某种方法可以做到这一点(毕竟,在调试应用程序时,VisualStudio会做到这一点),但它通常无法工作。

    eval (它不需要提供 动态范围界定 ,但它需要按名称访问变量)。因此,Phalanger检测函数是否包含对 评估 如果有,它会将所有变量存储在 Dictionary<string, object> 评估 函数(这样它就可以按名称读取变量)。恐怕这是唯一的办法。。。

        2
  •  8
  •   Eric Lippert    16 年前

    所以我的问题是,是否有可能通过使用反射来模拟.NET中的动态范围。

    反射支持在运行时操作在 元数据 属于 装配

    局部变量不是程序集元数据中表示的项。

    (如何)能够可靠地访问调用方法的局部变量?

    请注意,调试器不会 可靠地

    生产中的 “EVE”能力,想想JScript.NET,一种为这种东西而设计的语言。

    推荐文章