据我所知,没有直接的方法可以做到这一点。从 Visual Studio 中可靠地获取 AST(以及对其进行更改)一直是一个大问题。Rosalyn 项目的部分目标是创建一种统一的方式来执行此操作,因为许多工具窗口都有自己的方式来执行此类操作。
有四种方法可以做到这一点:
- 符号
- FileCodeModel + CodeDOM
- 罗莎琳 AST
- 未探索的方法
符号
我相信大多数工具窗口(例如 CodeView 和 Code Element Search 之类的东西)都使用从编译构建中创建的符号。这并不理想,因为它的重量有点重并且难以保持同步。您必须缓存符号以使其不慢。使用反射器,您可以看到 CodeView 如何实现这一点。
这种方法使用私有程序集。获取符号的代码如下所示:
var compilerHost = new IDECompilerHost();
var typeEnumerator = (from compiler in compilerHost.Compilers.Cast<IDECompiler>()
from type in compiler.GetCompilation().MainAssembly.Types
select new Tuple<IDECompiler, CSharpType>(compiler, type));
foreach (var typeTuple in typeEnumerator)
{
Trace.WriteLine(typeTuple.Item2.Name);
var csType = typeTuple.Item2;
foreach (var loc in csType.SourceLocations)
{
var file = loc.FileName.Value;
var line = loc.Position.Line;
var charPos = loc.Position.Character;
}
}
FileCodeModel + CodeDOM
您可以尝试使用 EnvDTE 服务来获取与代码文档关联的 FileCodeModel。这将使您获得类和方法。但它不支持获取方法体。你在搞乱有缺陷的 COM。这很难看,因为 COM 对象对 CodeFunction 或 CodeClass 的引用可能会在您不知情的情况下失效,这意味着您必须保留自己的镜像。
罗莎琳 AST
这允许提供与 FileCodeModel 和 Symbols 相同的功能。我一直在玩这个,它实际上并不算太糟糕。
未探索的方法
您可以尝试获取与代码文档关联的底层 LanguageServiceProvider。但这真的很难实现,并且会给您带来很多问题。