Getting Class FullName (including namespace) from Roslyn ClassDeclarationSyntax

偶尔善良 提交于 2019-12-04 23:41:18
Jordan

you can do this using the helper class I wrote:

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

and the helper:

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

There is nothing overly complex going on here... it makes sense that the namespace would be "up" the syntax tree (because the class is contained within the namespace) so you simply need to travel "up" the syntax tree until you find the namespace and append that to the identifier of the ClassDeclarationSyntax.

Try this code

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

Here is how I get the namespace. You have to slightly modify my code for your case:

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

I know I am rather late in the game, but I stumbled upon one of given the answers which did not work in my case where I had to deal with nested classes. So therefore here is a method that will handle nested classes as well:

public static class ClassDeclarationSyntaxExtensions
{
    public const string NESTED_CLASS_DELIMITER = "+";
    public const string NAMESPACE_CLASS_DELIMITER = ".";

    public static string GetFullName(this ClassDeclarationSyntax source)
    {
        Contract.Requires(null != source);

        var items = new List<string>();
        var parent = source.Parent;
        while (parent.IsKind(SyntaxKind.ClassDeclaration))
        {
            var parentClass = parent as ClassDeclarationSyntax;
            Contract.Assert(null != parentClass);
            items.Add(parentClass.Identifier.Text);

            parent = parent.Parent;
        }

        var nameSpace = parent as NamespaceDeclarationSyntax;
        Contract.Assert(null != nameSpace);
        var sb = new StringBuilder().Append(nameSpace.Name).Append(NAMESPACE_CLASS_DELIMITER);
        items.Reverse();
        items.ForEach(i => { sb.Append(i).Append(NESTED_CLASS_DELIMITER); });
        sb.Append(source.Identifier.Text);

        var result = sb.ToString();
        return result;
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!