从外部程序集获取 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();