Получение класса FullName (включая пространство имен) из Roslyn ClassDeclarationSyntax

У меня есть ClassDeclarationSyntax из дерева синтаксиса в roslyn. Я читал это так:

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

var classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>();

Идентификатор содержит только имя класса, но не содержит информации об пространстве имен, поэтому отсутствует имя полного типа. Как "MyClass", но noch "Namespace1.MyClass"

Каков рекомендуемый способ получить пространство имен /FulltypeName синтаксиса?

Ответ 1

вы можете сделать это, используя класс-помощник, который я написал:

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();

и помощник:

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;
        }
    }
}

Здесь нет ничего сложного, что происходит здесь... имеет смысл, что пространство имен будет "вверх" в дереве синтаксиса (потому что класс содержится в пространстве имен), поэтому вам просто нужно перемещать "вверх" дерево синтаксиса, пока не найдете пространство имен и добавьте его в идентификатор класса ClassDeclarationSyntax.

Ответ 2

Попробуйте этот код

public static string GetFullName(NamespaceDeclarationSyntax node)
{
    if (node.Parent is NamespaceDeclarationSyntax)
        return String.Format("{0}.{1}",
            GetFullName((NamespaceDeclarationSyntax)node.Parent),
            ((IdentifierNameSyntax)node.Name).Identifier.ToString());
    else
        return ((IdentifierNameSyntax)node.Name).Identifier.ToString();
}

Ответ 3

Вот как я получаю пространство имен. Вы должны немного изменить код для своего случая:

        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();
        }