首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从Roslyn ClassDeclarationSyntax获取类FullName (包括名称空间)

问从Roslyn ClassDeclarationSyntax获取类FullName (包括名称空间)
EN

Stack Overflow用户
提问于 2013-12-09 04:11:49
回答 8查看 9.2K关注 0票数 16

我有一个来自罗斯林语法树的ClassDeclarationSyntax。我是这样读的:

代码语言:javascript
复制
var tree = SyntaxTree.ParseText(sourceCode);
var root = (CompilationUnitSyntax)tree.GetRoot();

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

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

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

EN

回答 8

Stack Overflow用户

发布于 2014-04-23 23:33:54

您可以使用我编写的helper类来完成此操作:

代码语言:javascript
复制
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();

帮助者:

代码语言:javascript
复制
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的标识符。

票数 9
EN

Stack Overflow用户

发布于 2018-10-08 11:24:46

我知道我在游戏中相当晚,但我偶然发现了one of given the answers,它在我不得不处理嵌套类的情况下不起作用。因此,下面是一个处理嵌套类的方法:

代码语言:javascript
复制
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;
    }
}
票数 2
EN

Stack Overflow用户

发布于 2020-04-24 21:22:12

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

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

代码语言:javascript
复制
public static class TypeDeclarationSyntaxExtensions
{
    const char NESTED_CLASS_DELIMITER = '+';
    const char NAMESPACE_CLASS_DELIMITER = '.';
    const char TYPEPARAMETER_CLASS_DELIMITER = '`';

    public static string GetFullName(this TypeDeclarationSyntax source)
    {
        if (source is null)
            throw new ArgumentNullException(nameof(source));

        var namespaces = new LinkedList<NamespaceDeclarationSyntax>();
        var types = new LinkedList<TypeDeclarationSyntax>();
        for (var parent = source.Parent; parent is object; parent = parent.Parent)
        {
            if (parent is NamespaceDeclarationSyntax @namespace)
            {
                namespaces.AddFirst(@namespace);
            }
            else if (parent is TypeDeclarationSyntax type)
            {
                types.AddFirst(type);
            }
        }

        var result = new StringBuilder();
        for (var item = namespaces.First; item is object; item = item.Next)
        {
            result.Append(item.Value.Name).Append(NAMESPACE_CLASS_DELIMITER);
        }
        for (var item = types.First; item is object; item = item.Next)
        {
            var type = item.Value;
            AppendName(result, type);
            result.Append(NESTED_CLASS_DELIMITER);
        }
        AppendName(result, source);

        return result.ToString();
    }

    static void AppendName(StringBuilder builder, TypeDeclarationSyntax type)
    {
        builder.Append(type.Identifier.Text);
        var typeArguments = type.TypeParameterList?.ChildNodes()
            .Count(node => node is TypeParameterSyntax) ?? 0;
        if (typeArguments != 0)
            builder.Append(TYPEPARAMETER_CLASS_DELIMITER).Append(typeArguments);
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20458457

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档