4

我在嵌入式 REPL 中使用 Roslyn 脚本 API,有时我需要知道当前会话中定义了哪些变量,以及所有其他定义(类、接口...)以及哪些引用和导入的命名空间。

我在 API 中找不到任何可以给我那种信息的东西,我知道它就在某个地方。

Dose Scripting API 使用了一些不寻常的实现,比如每次都更新内存中的程序集?如果是这样,如何访问该程序集。

4

1 回答 1

6

我不知道是否有 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 子句不会给出预期的结果。

根据您想要查找的所有内容,还有更多可能有用的反射方法,例如GetMethodsGetEvents。如果你想要一切,那么有一个GetMembers See Type Methods

我希望有人可以提供一种更简单的方法。

于 2012-10-24T21:44:41.363 回答