从外部程序集获取 TypeSyntax 的命名空间
Gets TypeSyntax's namespace from external assembly
我正在尝试使用 Roslyn API 检索某些类型的命名空间,但我的代码无法使用外部程序集(来自 NuGet 包或其他外部程序集的类型):
var typeInfo = semanticModel.GetTypeInfo(typeSyntax);
var isFromSource = typeInfo.Type.Locations.Length > 0;
if (isFromSource)
{
var symbolInfo = semanticModel.GetSymbolInfo(typeSyntax);
//type's namespace:
return symbolInfo.Symbol.ContainingNamespace.ToString();
}
else
{
//Type is from some external assembly
return "";
}
在这种情况下,我如何 return 类型的命名空间?
编辑:
我正在检索解决方案的文档:
using (var ws = MSBuildWorkspace.Create())
{
var solution = await ws.OpenSolutionAsync(solutionPath);
return solution.Projects.SelectMany(p => p.Documents);
}
您确定在处理语法时没有编译错误并且正确解析了类型吗?
ContainingNamespace
属性 也应该为来自外部程序集的类型提供命名空间,只要类型可以解析即可。
如果有帮助,您可以在此处找到显示外部类型命名空间的片段(RestClient
class 来自 RestSharp nuget 包):
using System;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using RestSharp;
namespace Playground
{
public static class Program
{
public static void Main()
{
const string code =
@"using RestSharp;
namespace Playground
{
public class Foo
{
public void Bar(RestClient restClient)
{
}
}
}";
var tree = CSharpSyntaxTree.ParseText(code);
var compilation = CreateCompilation(tree);
var semanticModel = compilation.GetSemanticModel(tree);
var syntaxNode = GetParameterTypeSyntaxNode(tree);
Console.WriteLine(GetNamespace(syntaxNode, semanticModel));
}
private static TypeSyntax GetParameterTypeSyntaxNode(SyntaxTree tree) =>
tree.GetRoot()
.DescendantNodes()
.OfType<MethodDeclarationSyntax>()
.First()
.ParameterList
.Parameters
.First()
.Type;
private static INamespaceSymbol GetNamespace(SyntaxNode node, SemanticModel semanticModel) =>
semanticModel.GetTypeInfo(node).Type?.ContainingNamespace;
private static CSharpCompilation CreateCompilation(SyntaxTree tree) =>
CSharpCompilation
.Create("HiThere", options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
.AddReferences(MetadataReference.CreateFromFile(typeof(string).Assembly.Location))
.AddReferences(MetadataReference.CreateFromFile(typeof(RestClient).Assembly.Location))
.AddSyntaxTrees(tree);
}
}
这里的context是GeneratorExecutionContext,就是我们从Source GeneratorsExecute
方法参数中得到的
var @namespace = context
.Compilation?
.GetSemanticModel(type.SyntaxTree)?
.GetSymbolInfo(type)
.Symbol?
.ContainingNamespace?
.ToString();
我正在尝试使用 Roslyn API 检索某些类型的命名空间,但我的代码无法使用外部程序集(来自 NuGet 包或其他外部程序集的类型):
var typeInfo = semanticModel.GetTypeInfo(typeSyntax);
var isFromSource = typeInfo.Type.Locations.Length > 0;
if (isFromSource)
{
var symbolInfo = semanticModel.GetSymbolInfo(typeSyntax);
//type's namespace:
return symbolInfo.Symbol.ContainingNamespace.ToString();
}
else
{
//Type is from some external assembly
return "";
}
在这种情况下,我如何 return 类型的命名空间?
编辑: 我正在检索解决方案的文档:
using (var ws = MSBuildWorkspace.Create())
{
var solution = await ws.OpenSolutionAsync(solutionPath);
return solution.Projects.SelectMany(p => p.Documents);
}
您确定在处理语法时没有编译错误并且正确解析了类型吗?
ContainingNamespace
属性 也应该为来自外部程序集的类型提供命名空间,只要类型可以解析即可。
如果有帮助,您可以在此处找到显示外部类型命名空间的片段(RestClient
class 来自 RestSharp nuget 包):
using System;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using RestSharp;
namespace Playground
{
public static class Program
{
public static void Main()
{
const string code =
@"using RestSharp;
namespace Playground
{
public class Foo
{
public void Bar(RestClient restClient)
{
}
}
}";
var tree = CSharpSyntaxTree.ParseText(code);
var compilation = CreateCompilation(tree);
var semanticModel = compilation.GetSemanticModel(tree);
var syntaxNode = GetParameterTypeSyntaxNode(tree);
Console.WriteLine(GetNamespace(syntaxNode, semanticModel));
}
private static TypeSyntax GetParameterTypeSyntaxNode(SyntaxTree tree) =>
tree.GetRoot()
.DescendantNodes()
.OfType<MethodDeclarationSyntax>()
.First()
.ParameterList
.Parameters
.First()
.Type;
private static INamespaceSymbol GetNamespace(SyntaxNode node, SemanticModel semanticModel) =>
semanticModel.GetTypeInfo(node).Type?.ContainingNamespace;
private static CSharpCompilation CreateCompilation(SyntaxTree tree) =>
CSharpCompilation
.Create("HiThere", options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
.AddReferences(MetadataReference.CreateFromFile(typeof(string).Assembly.Location))
.AddReferences(MetadataReference.CreateFromFile(typeof(RestClient).Assembly.Location))
.AddSyntaxTrees(tree);
}
}
这里的context是GeneratorExecutionContext,就是我们从Source GeneratorsExecute
方法参数中得到的
var @namespace = context
.Compilation?
.GetSemanticModel(type.SyntaxTree)?
.GetSymbolInfo(type)
.Symbol?
.ContainingNamespace?
.ToString();