Get fully-qualified metadata name in Roslyn
Asked Answered
P

2

21

I need to get the full CLR name of a particular symbol. This means that for generic types I need the `1, `2, etc. appended to types. Now, ISymbol already has a property MetadataName which does exactly that. But it excludes surrounding types and namespaces, only giving the name of the symbol at hand.

The usual option for getting a fully-qualified name, i.e. via ToDisplayString doesn't quite work here because it will not use the MetadataName for its various parts.

Is there anything like this built-in? Or do I have to just concatenate the chain of ContainingSymbols with . in between? (And are there points where this assumption breaks down?)

EDIT: Just noticed that you need a + in between individual names if it's a type contained in another type, but apart from that, using . should work, I guess.

Proboscis answered 24/11, 2014 at 13:23 Comment(2)
Please support my Roslyn Issue on CodePlex for this feature: roslyn.codeplex.com/workitem/297Vaginectomy
A Roslyn team member created an issue for this, see github.com/dotnet/roslyn/issues/1891Grocer
P
21

For now, having no better solution, I'm using the following:

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

which seems to work for now. Roslyn seems to have internal flags for SymbolDisplayFormat that enable that sort of thing (most notably SymbolDisplayCompilerInternalOptions.UseArityForGenericTypes, but not accessible to the outside.

Above code could probably be faster on recent .NET versions by using Append instead of Insert on the StringBuilder, but that's something to leave for profiling.

Proboscis answered 24/11, 2014 at 14:20 Comment(0)
S
2

Surprisingly enough, but doing symbol.ToString() actually worked for me. That gave me a fully-qualified name with the namespace etc.

Smallsword answered 8/9, 2023 at 11:32 Comment(3)
It's not the metadata name, though, which shows nested types differently (+) and doesn't use the type parameter names, just the type parameter arity preceded with a backtick.Proboscis
Good point, although I guess that would still work pretty well with namespace names...Smallsword
This also doesn't take into account nested typesInternalize

© 2022 - 2024 — McMap. All rights reserved.