Get fully-qualified metadata name in Roslyn
c#, roslyn
Solution
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.
Problem
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 `ContainingSymbol`s 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.