Получение полного имени типа из объекта 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
.
Ответы
Ответ 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 }));
}
Очевидно, что ответ Джейсона Малиновского более удобен для простых случаев