我在嵌入式 REPL 中使用 Roslyn 脚本 API,有时我需要知道当前会话中定义了哪些变量,以及所有其他定义(类、接口...)以及哪些引用和导入的命名空间。
我在 API 中找不到任何可以给我那种信息的东西,我知道它就在某个地方。
Dose Scripting API 使用了一些不寻常的实现,比如每次都更新内存中的程序集?如果是这样,如何访问该程序集。
我不知道是否有 Roslyn 特定的 API,但看起来您可以使用 Reflection 获取信息。这有点麻烦。我在 Visual Studio 中使用 REPL 来近似您的情况。
using System.Reflection;
Assembly.GetExecutingAssembly().DefinedTypes
显示循环的每次迭代都有一个类型,以及定义的类的一些附加类型。幸运的是,这些Submission
类型被编号,后面的提交具有更高的编号,即Submission#11
紧随其后Submission#5
。
REPL 中定义的变量显示为会话类型中的字段,对应于定义它的循环的执行。查看类型中所有已定义变量的调用如下:
chosenType.GetFields(BindingFlags.Instance | BindingFlags.Public)
Roslyn REPL 允许您重新声明变量,将先前声明的变量屏蔽给新的调用者。现在将“会话”视为所有提交的堆栈(最旧的在底部)。如果您向下遍历堆栈,给定字段名称的第一次出现将是 REPL 中具有该名称的活动变量。检索到的字段信息除了名称之外还提供类型。
这是一个示例会话(包括输出),展示了如何查看会话中声明的所有变量。
> using System.Reflection;
> var a = 1;
> var b = "c";
> var c = from type in Assembly.GetExecutingAssembly().DefinedTypes.Reverse()
from variable in type.GetFields(BindingFlags.Instance | BindingFlags.Public)
select variable;
> foreach (var info in c ) {
if (info.FieldType != typeof(Roslyn.Services.InteractiveHostObject)) {
Console.WriteLine(info);
}
}
System.Collections.Generic.IEnumerable`1[System.Reflection.FieldInfo] c
System.String b
Int32 a
如果相同的名称出现两次,则列出的第一个名称是会话中可用的名称。以上利用了返回的类型恰好按从旧到新排序的事实。您可能希望自己对其进行排序以确定。
无论出于何种原因(可能是错误?)我必须在 foreach 循环中使用 if 语句,使用 LINQ where 子句不会给出预期的结果。
根据您想要查找的所有内容,还有更多可能有用的反射方法,例如GetMethods
和GetEvents
。如果你想要一切,那么有一个GetMembers
See Type Methods。
我希望有人可以提供一种更简单的方法。