Получить полное имя метаданных в Roslyn

Мне нужно получить полное CLR-имя определенного символа. Это означает, что для общих типов мне нужны типы `1, `2 и т.д., Добавленные к типам. Теперь ISymbol уже имеет свойство MetadataName, которое делает именно это. Но он исключает окружающие типы и пространства имен, давая только имя символа.

Обычная опция для получения полного имени, т.е. через ToDisplayString, здесь не совсем работает, потому что она не будет использовать MetadataName для своих различных частей.

Есть ли что-то вроде этого встроенного? Или мне нужно просто конкатенировать цепочку ContainingSymbol с помощью . между ними? (И есть ли точки, где это предположение ломается?)

EDIT: Просто заметили, что вам нужно + между отдельными именами, если это тип, содержащийся в другом типе, но кроме этого использование . должно работать, я думаю.

Ответ 1

Теперь, не имея лучшего решения, я использую следующее:

public static string GetFullMetadataName(this INamespaceOrTypeSymbol symbol) 
{
    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, используя Append вместо Insert на StringBuilder, но что-то, что нужно оставить для профилирования.