C#Roslyn编译器 - 如何从IdentifierNameSyntax获取类型的命名空间?

时间:2017-08-10 12:21:59

标签: c# roslyn roslyn-code-analysis

假设我在代码SomeClass.SomeStaticMethod<T>()中有一个调用,它是一个InvocationExpressionSyntax。

我将泛型类型T的名称作为字符串(来自IdentifierNameSyntax)。我试图获得T的象征,但我没有成功。

如何查找T类型的命名空间信息?

更新:@SJP的回答是正确的。我想为那些想要从IdentifierNameSyntax获取名称空间信息的人解释我的错误,该名称包含类(类名)的标识符:

我最初的目标是以SomeClass.SomeMethod<T>()格式查找调用并获取类型为T的命名空间信息。

var namedTypeSymbol = context.Symbol as INamedTypeSymbol;
var reference = nameTypeSymbol.DeclaringSyntaxReferences.First();
var classSyntaxTree = reference.SyntaxTree;

var semanticModel = context.Compilation.GetSemanticModel(classSyntaxTree);
var genericNameSyntax = (GenericNameSyntax)((MemberAccessExpressionSyntax)node.Expression).Name;
var identifierNameSyntax = genericNameSyntax.TypeArgumentList.Arguments.First();
var typeInfo = semanticModel.GetTypeInfo(identifierNameSyntax);
var nameSpace = ((INamedTypeSymbol)typeInfo.Type).ContainingNamespace;
var nameSpaceName = nameSpace.ToString();

这是我的错误:

我尝试获取<module_name>.<namespace_part_1>.<namespace_part_2>这样的完整名称空间,但当我namedTypeSymbol.ContainingNamespace.Name时,我只获得了<namespace_part_2>。几个小时后,我发现获得完整的命名空间就像namedTypeSymbol.ContainingNamespace.ToString()一样。

有时候,最好的办法就是到户外呼吸新鲜空气:)

1 个答案:

答案 0 :(得分:3)

您将需要语义模型来完成您的任务。假设您需要SomeClass的命名空间,那么您可以通过访问Expression的Name Field来从MemberAccessExpressionSyntax中获取名称空间的类型和名称,如下所示:

var semanticModel = await document.GetSemanticModelAsync()
var name = (GenericNameSyntax)((MemberAccessExpressionSyntax)node.Expression).Name;
var typeInfo = semanticModel.GetTypeInfo(name.TypeArgumentList.Arguments.First());
var nameSpace = ((INamedTypeSymbol)typeInfo.Type).ContainingNamespace;
var nameSpaceName = nameSpace.Name;

对于以下示例程序,这将导致变量nameSpaceName的“System”或“ConsoleApp1”(取决于调用),而变量nameSpace可以访问所有其他信息。

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Program.DoStuff<string>();
            Program.DoStuff<Program>();
        }

        static void DoStuff<T>()
        {

        }
    }
}