Question Obtenir le nom complet d'un type à partir d'un objet TypeInfo


Est-il possible d'obtenir le nom complet du type contenu dans un TypeInfo objet?

Dans le débogueur beaucoup de ces valeurs apparaissent bien comme System.Int32 mais quand il est imprimé, aucun d'entre eux ne contient ce nom complet. J'ai besoin de cela pour fournir un argument à 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

Notez que cela devrait fonctionner pour tous les types, donc je ne peux pas simplement concaténer l'espace de noms avec le nom.

Autre solution: existe-t-il une autre méthode (plus adaptée?) Pour obtenir le type exact?

Pour le contexte: je veux vérifier si les paramètres de type d'une classe contiennent quelques méthodes spécifiques. Par conséquent, mon approche consistait à obtenir les paramètres du TypeArgumentListSyntax et obtenir le TypeInfo de chaque TypeSyntax objet.


13
2018-04-26 01:39


origine


Réponses:


le ToDisplayString La méthode vous permet de passer dans un objet "format" qui dispose d'un grand nombre d'options pour contrôler la manière dont vous souhaitez formater les choses:

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

string fullyQualifiedName = typeSymbol.ToDisplayString(symbolDisplayFormat);

La raison pour laquelle vos mots-clés comme "int" sont le format par défaut est la SymbolDisplayMiscellaneousOptions.UseSpecialTypes flag qui spécifie d'utiliser les mots-clés de langue pour les types spéciaux par rapport au nom normal.


23
2018-04-26 18:31



Je ne pouvais pas trouver quelque chose intégré non plus et je suis certain que ce n'est pas la manière la plus élégante, mais cela a fonctionné pour moi de construire un nom de type qualifié comme ceci:

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

Si vous n'avez pas besoin d'un type qualifié d'assembly, ne concaténez pas ContainingAssembly à la fin de la dernière ligne.


3
2018-04-26 08:57



En utilisant le modèle sémantique, vous pouvez aussi le faire comme je l'ai fait ici:

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;

où "GetFullNamespace" fonctionne comme ceci:

    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 }));
    }

De toute évidence, la réponse de Jason Malinowski est plus pratique pour les cas simples


0
2018-03-28 14:49