从TypeInfo对象获取类型的完全限定名称

时间:2014-04-26 01:39:14

标签: c# roslyn

是否有可能获得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

3 个答案:

答案 0 :(得分:23)

ToDisplayString方法可让您传入"格式"对象,它有很多选项来控制你想要格式化的东西:

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

string fullyQualifiedName = typeSymbol.ToDisplayString(symbolDisplayFormat);

您获得" int"等关键字的原因是默认格式,包括SymbolDisplayMiscellaneousOptions.UseSpecialTypes标志,该标志指定使用特殊类型的语言关键字与常规名称。

答案 1 :(得分:3)

我找不到内置的东西,我很确定这不是最优雅的方式,但是我可以构建一个像这样的合格类型名称:

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

如果您不需要程序集限定类型名称,请不要在最后一行的末尾连接ContainingAssembly

答案 2 :(得分:0)

使用语义模型你也可以像我在这里做的那样:

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

显然,Jason Malinowski的回答对于简单案例来说更方便