从Roslyn ClassDeclarationSyntax获取类FullName(包括命名空间)

Boa*_*ler 14 c# roslyn

我在roslyn的语法树中有一个ClassDeclarationSyntax.我这样看了:

var tree = SyntaxTree.ParseText(sourceCode);
var root = (CompilationUnitSyntax)tree.GetRoot();

var classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>();
Run Code Online (Sandbox Code Playgroud)

标识符仅包含类的名称,但不包含有关命名空间的信息,因此缺少fullType名称.像"MyClass"但是noch"Namespace1.MyClass"

获取语​​法的名称空间/ FulltypeName的推荐方法是什么?

Jor*_*dan 5

你可以使用我写的助手类来做到这一点:

NamespaceDeclarationSyntax namespaceDeclarationSyntax = null;
if (!SyntaxNodeHelper.TryGetParentSyntax(classDeclarationSyntax, out namespaceDeclarationSyntax))
{
    return; // or whatever you want to do in this scenario
}

var namespaceName = namespaceDeclarationSyntax.Name.ToString();
var fullClassName = namespaceName + "." + classDeclarationSyntax.Identifier.ToString();
Run Code Online (Sandbox Code Playgroud)

和助手:

static class SyntaxNodeHelper
{
    public static bool TryGetParentSyntax<T>(SyntaxNode syntaxNode, out T result) 
        where T : SyntaxNode
    {
        // set defaults
        result = null;

        if (syntaxNode == null)
        {
            return false;
        }

        try
        {
            syntaxNode = syntaxNode.Parent;

            if (syntaxNode == null)
            {
                return false;
            }

            if (syntaxNode.GetType() == typeof (T))
            {
                result = syntaxNode as T;
                return true;
            }

            return TryGetParentSyntax<T>(syntaxNode, out result);
        }
        catch
        {
            return false;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这里没有任何过于复杂的东西......有意义的是命名空间会"升级"语法树(因为类包含在命名空间中)所以你只需要"向上"语法树,直到找到命名空间并将其附加到标识符ClassDeclarationSyntax.

  • @johnny5我认为`DescendantNodes`在语法树中是错误的方向,因为它向下而不是向上。我通过使用 `syntaxNode.Ancestors().OfType&lt;NamespaceDeclarationSyntax&gt;();` 解决了这个问题 (2认同)

Arl*_*dua 5

使用模式匹配+递归还有一种优雅的方式:

// method with pattern matching
public static string GetNamespaceFrom(SyntaxNode s) =>
    s.Parent switch
    {
        NamespaceDeclarationSyntax namespaceDeclarationSyntax => namespaceDeclarationSyntax.Name.ToString(),
        null => string.Empty, // or whatever you want to do
        _ => GetNamespaceFrom(s.Parent)
    };

// somewhere call it passing the class declaration syntax:
string ns = GetNamespaceFrom(classDeclarationSyntax);
Run Code Online (Sandbox Code Playgroud)


Ale*_*lex 5

ITypeSymbol为您的类定义构建一个。

然后获取它的“完整限定名称”

ClassDeclarationSyntax myclass; //your class here

var typeSymbol = context.Compilation.GetSemanticModel(myclass.SyntaxTree).GetDeclaredSymbol(myclass);

typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
//-------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^this
Run Code Online (Sandbox Code Playgroud)


myn*_*kow 0

这是我获取命名空间的方法。您必须根据您的情况稍微修改我的代码:

        public static async Task<NamespaceDeclarationSyntax> GetNamespaceAsync(this Document document, CancellationToken cancellationToken = default(CancellationToken))
        {
            SyntaxNode documentRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
            var rootCompUnit = (CompilationUnitSyntax)documentRoot;
            return (NamespaceDeclarationSyntax)rootCompUnit.Members.Where(m => m.IsKind(SyntaxKind.NamespaceDeclaration)).Single();
        }
Run Code Online (Sandbox Code Playgroud)

  • 我认为这只是故事的一半。如果命名空间是嵌套的怎么办?我建议您一直向上直到到达起点。 (4认同)