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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With