如何获取声明的变量和其他定义

时间:2012-10-24 19:20:40

标签: c# scripting roslyn

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

我在API中找不到任何可以给我这种信息的东西,我知道它在某处。

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

1 个答案:

答案 0 :(得分:6)

我不知道是否有特定于Roslyn的API,但看起来您可以使用Reflection获取信息。这是一件苦差事。我在Visual Studio中使用REPL来估计您的情况。

using System.Reflection;

Assembly.GetExecutingAssembly().DefinedTypes

显示循环的每次迭代都有一个类型,另外还有一些用于定义的类。幸运的是,Submission类型的编号后来提交的数字更高,Submission#11位于Submission#5之后。

REPL中定义的变量在Session类型中显示为字段,该字段对应于定义它的循环的执行。查看类型中所有已定义变量的调用如下:

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

如果同一名称出现两次,则列出的第一个名称是会话中可用的名称。以上内容利用了类型返回恰好最老到最年轻的事实。您可能希望自己对其进行排序以确定。

无论出于何种原因(bug可能?)我必须在foreach循环中使用if语句,使用LINQ where子句不会给出预期的结果。

根据您想要查找的内容,还有更多可能有用的反射方法,例如GetMethodsGetEvents。如果您想要所有内容,则可以GetMembers查看Type Methods

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