2015-11-27 2 views
4

я успешно получил в ITypeSymbol из SyntaxNode с помощью:Как сравнить Microsoft.CodeAnalysis.ITypeSymbol к System.Type

SemanticModel.GetTypeInfo(sytaxNode).ConvertedType 

Теперь я хотел бы знать, если это ITypeSymbol соответствует System.Type примеру который присутствует в моем исполняемом коде, например typeof(IEnumerable<int>) или someObject.GetType().

Я попытался

typeInfo.ConvertedType.ToString() == type.ToString() 

Но они не используют одни и те же правила форматирования, например, для дженериков как IEnumerable<int>

TypeInfo.ToString() == "System.Collections.Generic.IEnumerable<int>"

в то время как

typeof(IEnumerable<int>).ToString() == "System.Collections.Generic.IEnumerable`1[System.Int32]" 

Кроме того, я думаю, что это было бы лучше сравнить AssemblyQuali fiedNames вместо простого пространства имен и имени типа, чтобы избежать возможных конфликтов имен.

В идеале, я хотел бы иметь возможность получить фактический экземпляр System.Type в моем исполняемом коде, который соответствует ITypeInfo, полученному из семантической модели (при условии, что необходимая сборка загружена и/или доступна). Это позволит проверить, является ли тип назначаемым из какого-либо другого типа и т. Д.

+0

Возможный дубликат [SemanticModel.GetTypeInfo() для ObjectCreationExpressionSyntax.Type возвращает нуль] (http://stackoverflow.com/questions/27535382/semanticmodel-gettypeinfo-for-objectcreationexpressionsyntax-type-returns-null) – MethodMan

+1

Не дубликат, этот вопрос касается того, как получить TypeInfo, этот вопрос касается того, как сравнить TypeInfo с типом –

+0

. Если вы можете получить TypeInfo, я подумал, что вы можете сравнить, но, возможно, я ошибаюсь, может быть, мое понимание относится к этой ссылке в отношении вашего последнего комментария http://stackoverflow.com/questions/28240167/correct-way-to-check-the-type-of-an-expression-in-roslyn-analyzer – MethodMan

ответ

6

Вы можете получить INamedTypeSymbol для названия типа с Compilation.GetTypeByMetadataName().

Так попробуйте это:

semanticModel.GetTypeInfo(sytaxNode).ConvertedType.Equals(
    semanticModel.Compilation.GetTypeByMetadataName(typeof(WhateverType).FullName)) 

Это не будет работать с закрытыми родовыми типами, для тех, вам нужно сделать немного больше. Например:

var ienumerableType = semanticModel.Compilation.GetTypeByMetadataName("System.Collections.Generic.IEnumerable`1"); 
var intType = semanticModel.Compilation.GetTypeByMetadataName("System.Int32"); 
var type = ienumerableType.Construct(intType); 
+0

Действительно, это трюк, более общее решение потребует некоторой рекурсии таким образом, но должно быть выполнимым Я думаю, –

+0

Ну, я получаю null для ienumerableType и intType, любые идеи почему? – SARI

4

На основании ответа от @Tamas, я создал следующее рекурсивное решение, которое работает для закрытых универсальных типов.

static bool TypeSymbolMatchesType(ITypeSymbol typeSymbol, Type type, SemanticModel semanticModel) 
    { 
     return GetTypeSymbolForType(type, semanticModel).Equals(typeSymbol); 
    } 

    static INamedTypeSymbol GetTypeSymbolForType(Type type, SemanticModel semanticModel) 
    { 

     if (!type.IsConstructedGenericType) 
     { 
      return semanticModel.Compilation.GetTypeByMetadataName(type.FullName); 
     } 

     // get all typeInfo's for the Type arguments 
     var typeArgumentsTypeInfos = type.GenericTypeArguments.Select(a => GetTypeSymbolForType(a, semanticModel)); 

     var openType = type.GetGenericTypeDefinition(); 
     var typeSymbol = semanticModel.Compilation.GetTypeByMetadataName(openType.FullName); 
     return typeSymbol.Construct(typeArgumentsTypeInfos.ToArray<ITypeSymbol>()); 
    } 
Смежные вопросы