如何访问项目代码元数据

本文关键字:项目 代码 元数据 访问 何访问 | 更新日期: 2023-09-27 18:33:36

在我的VSPackage中,我需要将代码中对属性的引用替换为其实际值。例如

public static void Main(string[] args) {
    Console.WriteLine(Resource.HelloWorld);
}

我想要的是将"Resource.HelloWorld"替换为它的实际值 - 即找到类Resource并获取其静态属性HelloWorld的值。Visual Studio是否公开任何API来处理项目的代码模型?它肯定有一个,因为这与重命名变量的常见任务非常相似。我不想在输出程序集上使用反射,因为它很慢并且会锁定文件一段时间。

如何访问项目代码元数据

据我所知,没有直接的方法可以做到这一点。 可靠地从Visual Studio中获取AST(以及对它的更改(一直是一个大问题。Rosalyn 项目的部分目标是创建一种统一的方式来做到这一点,因为许多工具窗口都有自己的方法来做这类事情。

有四种方法可以做到这一点:

  1. 符号
  2. 文件代码模型 + 代码DOM
  3. 罗莎琳·阿斯特
  4. 未探索的方法

符号

我相信大多数工具窗口(如 CodeView 和代码元素搜索(都使用从编译版本创建的符号。 这并不理想,因为它的重量有点重,很难保持同步。 您必须缓存符号才能使其不慢。 使用反射器,您可以看到 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;
    }
}

文件代码模型 + 代码DOM

您可以尝试使用 EnvDTE 服务来获取与代码文档关联的 FileCodeModel。 这将允许您获取类和方法。 但它不支持获取方法主体。 你搞砸了有缺陷的 COM。 这很丑陋,因为对CodeFunction或CodeClass的COM对象引用可能会在您不知情的情况下失效,这意味着您必须保留自己的镜像。

罗莎琳·阿斯特

这允许提供与文件代码模型和符号相同的功能。 我一直在玩这个,实际上还不错。

未探索的方法

您可以尝试获取与代码文档关联的基础语言服务提供程序。 但这真的很难实现,并且给您留下了许多问题。