0

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

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

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

4

1 回答 1

3

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

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

  1. 符号
  2. FileCodeModel + CodeDOM
  3. 罗莎琳 AST
  4. 未探索的方法

符号

我相信大多数工具窗口(例如 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。但这真的很难实现,并且会给您带来很多问题。

于 2012-05-17T20:13:32.920 回答