0

私の VSPackage では、コード内のプロパティへの参照を実際の値に置き換える必要があります。例えば

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

私が望むのは、「Resource.HelloWorld」をその実際の値に置き換えることです。つまり、クラス Resource を見つけて、その静的プロパティ HelloWorld の値を取得します。Visual Studio は、プロジェクトのコード モデルを処理する API を公開していますか? これは、変数の名前を変更する一般的なタスクと非常に似ているためです。出力アセンブリでリフレクションを使用したくありません。処理が遅く、ファイルがしばらくロックされるからです。

4

1 に答える 1

3

There is no straight forward way to do this that I know of. Reliably getting an AST out of Visual Studio (and changes to it) has always been a big problem. Part of the goal of the Rosalyn project is to create an unified way of doing this, because many tool windows had their own way of doing this sort of stuff.

There are four ways to do this:

  1. Symbols
  2. FileCodeModel + CodeDOM
  3. Rosalyn AST
  4. Unexplored Method

Symbols

I believe most tool windows such as the CodeView and things like Code Element Search use the symbols created from a compiled build. This is not ideal as it is a little more heavy weight and hard to keep in sync. You'd have to cache symbols to make this not slow. Using reflector, you can see how CodeView implements this.

This approach uses private assemblies. The code for getting the symbols would look something like this:

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

You could try using the EnvDTE service to get the FileCodeModel associated with a Code Document. This will let you get classes and methods. But it does not support getting the method body. You're messing with buggy COM. This ugly because an COM object reference to a CodeFunction or CodeClass can get invalided without you knowing it, meaning you'd have to keep your own mirror.

Rosalyn AST

This allows provides the same capabilities as both FileCodeModel and Symbols. I've been playing with this and it's actually not too bad.

Unexplored Method

You could try getting the underlying LanguageServiceProvider that is associated with the Code Document. But this is really difficult to pull off, and leaves you with many issues.

于 2012-05-17T20:13:32.920 に答える