背景
尽管可以在运行时编译 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
}
所以我的问题是是否可以通过使用反射来模拟 .NET 中的动态作用域。
反射允许运行时操作在metadata of an assembly.
局部变量不是在程序集的元数据中表示的项目。
因此,你的问题的答案是“不”。
(如何)是否可以可靠地访问调用方法的局部变量?
访问调用方法的局部变量的设备称为“调试器”。所以你的问题的答案是“自己写一个调试器”。
请注意,调试器不reliably通过代码优化访问世界中的当地人。局部变量可以被优化掉,抖动可以生成对两个不同局部变量使用相同寄存器的代码,堆栈帧可以在尾部调用期间重新使用,等等。当然,您最好拥有 PDB 文件来告诉调试器与每个堆栈帧位置关联的名称是什么。
您的方法必须做的是将自定义调试器作为新进程启动,然后等待调试器向其发送消息。然后,调试器将挂起原始进程的线程,询问堆栈帧,然后恢复该进程的线程。然后它会向调试对象发送包含您发现的信息的消息。由于调试对象正处于等待状态等待消息,因此它将恢复其业务。
如果你想要的是一个进行中“评估”功能,请考虑 JScript.NET,这是一种专为此类事情而设计的语言。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)