在Roslyn中获取完全限定的元数据名称

20
我需要获取特定符号的完整CLR名称。这意味着对于泛型类型,我需要将`1`2等附加到类型上。现在,ISymbol已经有一个属性MetadataName来实现这一点。但它不包括周围的类型和命名空间,只给出手头符号的名称。
通常获取完全限定名称的选项,即通过ToDisplayString,在这里并不起作用,因为它不会使用MetadataName的各个部分。
是否内置了类似此功能的内容?还是我必须只需连接ContainingSymbol链,并在其中放置(这种假设何时会失败?)
编辑:刚注意到如果它是包含在另一个类型中的类型,则需要在各个名称之间加上+,但除此以外,使用应该可以工作,我想。

1
请支持我的Roslyn问题在CodePlex上为此功能:https://roslyn.codeplex.com/workitem/297 - JoshVarty
1
Roslyn团队成员为此创建了一个问题,请参见https://github.com/dotnet/roslyn/issues/1891 - bkoelman
2个回答

20

目前没有更好的解决方案,所以我正在使用以下方法:

public static string GetFullMetadataName(this ISymbol s) 
{
    if (s == null || IsRootNamespace(s))
    {
        return string.Empty;
    }

    var sb = new StringBuilder(s.MetadataName);
    var last = s;

    s = s.ContainingSymbol;

    while (!IsRootNamespace(s))
    {
        if (s is ITypeSymbol && last is ITypeSymbol)
        {
            sb.Insert(0, '+');
        }
        else
        {
            sb.Insert(0, '.');
        }

        sb.Insert(0, s.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat));
        //sb.Insert(0, s.MetadataName);
        s = s.ContainingSymbol;
    }

    return sb.ToString();
}

private static bool IsRootNamespace(ISymbol symbol) 
{
    INamespaceSymbol s = null;
    return ((s = symbol as INamespaceSymbol) != null) && s.IsGlobalNamespace;
}

目前看起来是有效的。 Roslyn似乎具有SymbolDisplayFormat的内部标志,可以启用这种功能(尤其是SymbolDisplayCompilerInternalOptions.UseArityForGenericTypes),但对外不可访问。

在最新的.NET版本上,上述代码可能会更快,方法是使用StringBuilder上的Append而不是Insert,但这是留给性能分析的。


0
令人惊讶的是,但是对我来说,使用symbol.ToString()实际上是有效的。这给了我一个带有命名空间等完整限定名称。

1
不过,显示嵌套类型的并不是元数据名称(+),而是使用类型参数的数量前面加上反引号,而不是使用类型参数的名称。 - undefined
好观点,虽然我猜在命名空间名称方面仍然能很好地发挥作用。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接