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

时间:2013-12-08 20:11:49

标签: c# roslyn

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

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

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

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

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

7 个答案:

答案 0 :(得分: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();

和帮手:

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

这里没有任何过于复杂的事情......命名空间将是&#34; up&#34;语法树(因为类包含在命名空间中)所以你只需要旅行&#34; up&#34;语法树,直到找到命名空间并将其附加到ClassDeclarationSyntax的标识符。

答案 1 :(得分:1)

试试此代码

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

答案 2 :(得分:1)

基于the answer by Ronald,我添加了对以下内容的支持:嵌套名称空间,结构和泛型。

它使用generics CLR naming convention来允许输出用作Compilation.GetTypeByMetadataName()的输入

option 1

答案 3 :(得分:1)

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

def job(hours,rate):
       if hours < 40:
           sm = hours * rate
           print(sm)
       elif hours > 40:
           sm = 40 * rate
           ov = ((hours - 40) * rate) * 0.5
           tt = sm + ov
           print(tt)
       
a = float(input())
b = float(input())

print(job(a,b))
print("Fine") 

答案 4 :(得分: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();
        }

答案 5 :(得分:0)

我知道我已经很晚了,但是我偶然发现one of given the answers在我不得不处理嵌套类的情况下不起作用。因此,这是一种也可以处理嵌套类的方法:

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

答案 6 :(得分:0)

另一个答案。.该实用工具类支持嵌套的名称空间和嵌套的类。

public static class SyntaxNodeHelper
{
    public static string GetPrefix(SyntaxNode member)
    {
        if (member == null) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        SyntaxNode node = member;

        while(node.Parent != null) {
            node = node.Parent;

            if (node is NamespaceDeclarationSyntax) {
                var namespaceDeclaration = (NamespaceDeclarationSyntax) node;

                sb.Insert(0, ".");
                sb.Insert(0, namespaceDeclaration.Name.ToString());
            } else if (node is ClassDeclarationSyntax) {
                var classDeclaration = (ClassDeclarationSyntax) node;

                sb.Insert(0, ".");
                sb.Insert(0, classDeclaration.Identifier.ToString());
            }
        }

        return sb.ToString();
    }
}