C# Roslyn 编译器 - 如何从 IdentifierNameSyntax 获取类型的命名空间?
C# Roslyn Compiler - How to get namespace of a type from IdentifierNameSyntax?
假设我在代码中有一个调用,SomeClass.SomeStaticMethod<T>()
,它是一个 InvocationExpressionSyntax。
我得到泛型类型 T 的名称作为字符串(来自 IdentifierNameSyntax)。我尝试获取 T 的符号,但我没有成功。
如何查看类型T的命名空间信息?
更新:@SJP 的回答是正确的。我想向那些想从 IdentifierNameSyntax 获取名称空间信息的人解释我的错误,其中包含 class(class 名称)的标识符:
我最初的目标是找到 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()
.
有时候最好的办法就是出去呼吸新鲜空气:)
您将需要语义模型来完成您的任务。假设您需要 SomeClass 的命名空间,那么您可以通过访问表达式的名称字段,从 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>()
{
}
}
}
对 Function{SuppliedArgument}(...) 的调用将有一个 GenericNameSyntax 作为 {SuppliedArgument}。这与 TypeDeclaration.TypeParameterList.Parameters 不同。你不能从那些东西中得到任何东西。它们是占位符。您需要遍历 GenericNameSyntax.TypeArgumentList,并在每个上使用 SemanticModel.GetSymbolInfo(identifierNameSyntax).Symbol.ContainingNamespace 以获取包含标识符的命名空间。
假设我在代码中有一个调用,SomeClass.SomeStaticMethod<T>()
,它是一个 InvocationExpressionSyntax。
我得到泛型类型 T 的名称作为字符串(来自 IdentifierNameSyntax)。我尝试获取 T 的符号,但我没有成功。
如何查看类型T的命名空间信息?
更新:@SJP 的回答是正确的。我想向那些想从 IdentifierNameSyntax 获取名称空间信息的人解释我的错误,其中包含 class(class 名称)的标识符:
我最初的目标是找到 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()
.
有时候最好的办法就是出去呼吸新鲜空气:)
您将需要语义模型来完成您的任务。假设您需要 SomeClass 的命名空间,那么您可以通过访问表达式的名称字段,从 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>()
{
}
}
}
对 Function{SuppliedArgument}(...) 的调用将有一个 GenericNameSyntax 作为 {SuppliedArgument}。这与 TypeDeclaration.TypeParameterList.Parameters 不同。你不能从那些东西中得到任何东西。它们是占位符。您需要遍历 GenericNameSyntax.TypeArgumentList,并在每个上使用 SemanticModel.GetSymbolInfo(identifierNameSyntax).Symbol.ContainingNamespace 以获取包含标识符的命名空间。