Подтвердить что ты не робот

Получение полного имени типа из объекта TypeInfo

Как можно получить полное имя типа, содержащегося в объекте TypeInfo?

В отладчике многие из этих значений хорошо отображаются как System.Int32, но когда он распечатывается, ни одно из них не содержит это полное имя. Мне нужно это, чтобы предоставить аргумент Type.GetType().

var typeInfo = semanticModel.GetTypeInfo(argument);
var w = typeInfo.ToString(); // Microsoft.CodeAnalysis.TypeInfo
var y = typeInfo.Type.ToString(); // int
var z = typeInfo.Type.ToDisplayString(); // int 
var a = typeInfo.Type.OriginalDefinition.ToDisplayString(); // int
var b = typeInfo.Type.OriginalDefinition.ToString(); // int
var c = typeInfo.Type.Name; // Int32
var d = typeInfo.Type.MetadataName; // Int32
var e = typeInfo.Type.ToDisplayParts(); // {int}
var f = typeInfo.Type.ContainingNamespace; // System

Обратите внимание, что это должно работать для каждого типа, поэтому я не могу просто конкатенировать пространство имен с именем.

Альтернативно: есть ли другой (более подходящий?) способ получить точный тип?

В контексте: я хочу проверить, содержат ли параметры типа класса несколько определенных методов. Поэтому мой подход состоял в том, чтобы получить параметры из TypeArgumentListSyntax и получить TypeInfo от каждого объекта TypeSyntax.

4b9b3361

Ответ 1

Метод ToDisplayString позволяет вам передать объект "format", который имеет огромное количество опций для управления тем, как вы хотите форматировать материал:

var symbolDisplayFormat = new SymbolDisplayFormat(
    typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces);

string fullyQualifiedName = typeSymbol.ToDisplayString(symbolDisplayFormat);

Причина, по которой ваши ключевые слова типа "int" - это формат по умолчанию, включает флаг SymbolDisplayMiscellaneousOptions.UseSpecialTypes, который указывает использование ключевых слов языка для специальных типов по сравнению с обычным именем.

Ответ 2

Я тоже не мог найти что-то встроенное, и я уверен, что это не самый элегантный способ, но для меня это создало квалифицированное имя типа:

private static string GetQualifiedTypeName(ISymbol symbol)
{
    return symbol.ContainingNamespace 
        + "." + symbol.Name 
        + ", " + symbol.ContainingAssembly;
}

Если вам не требуется имя типа сборки, не конкатенируйте ContainingAssembly в конце последней строки.

Ответ 3

Используя семантическую модель, вы также можете сделать это, как я сделал это здесь:

var typeInfo = context.SemanticModel.GetTypeInfo(identifierNameSyntax);
var namedType = typeInfo.Type as INamedTypeSymbol;
if (namedType != null && namedType.Name == nameof(ConfiguredTaskAwaitable) && GetFullNamespace(namedType) == typeof(ConfiguredTaskAwaitable).Namespace)
    return true;

где "GetFullNamespace" работает следующим образом:

    public static IEnumerable<string> GetNamespaces(INamedTypeSymbol symbol)
    {
        var current = symbol.ContainingNamespace;
        while (current != null)
        {
            if (current.IsGlobalNamespace)
                break;
            yield return current.Name;
            current = current.ContainingNamespace;
        }
    }

    public static string GetFullNamespace(INamedTypeSymbol symbol)
    {
        return string.Join(".", GetNamespaces(symbol).Reverse());
    }

    public static string GetFullTypeName(INamedTypeSymbol symbol)
    {
        return string.Join(".", GetNamespaces(symbol).Reverse().Concat(new []{ symbol.Name }));
    }

Очевидно, что ответ Джейсона Малиновского более удобен для простых случаев