如何访问项目代码元数据?

时间:2012-05-09 20:52:53

标签: c# visual-studio vsx vspackage

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

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

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

1 个答案:

答案 0 :(得分:3)

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

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

  1. 符号
  2. FileCodeModel + CodeDOM
  3. Rosalyn AST
  4. 未探索的方法
  5. <强>符号

    我相信大多数工具窗口(如CodeView)和C​​ode 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。这很难看,因为对CodeFunction或CodeClass的COM对象引用可能会在您不知情的情况下被无效,这意味着您必须保留自己的镜像。

    <强> Rosalyn AST

    这允许提供与FileCodeModel和Symbols相同的功能。我一直在玩这个,实际上并不太糟糕。

    未经探索的方法

    您可以尝试获取与代码文档关联的基础LanguageServiceProvider。但这真的很难实现,并且给你留下了许多问题。