2015-01-30 2 views
12

Ich schreibe einen Code-Analysator mit Roslyn, und ich muss überprüfen, ob ein ExpressionSyntax vom Typ Task oder Task<T> ist.Korrekte Möglichkeit, den Typ eines Ausdrucks im Roslyn Analyzer zu überprüfen?

Bisher habe ich dies:

private static bool IsTask(ExpressionSyntax expression, SyntaxNodeAnalysisContext context) 
{ 
    var type = context.SemanticModel.GetTypeInfo(expression).Type; 
    if (type == null) 
     return false; 
    if (type.Equals(context.SemanticModel.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task"))) 
     return true; 
    if (type.Equals(context.SemanticModel.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task`1"))) 
     return true; 
    return false; 
} 

Es funktioniert für Task, aber nicht für Task<int> oder Task<string> ... Ich konnte den Namen und Namensraum überprüfen, aber es ist unpraktisch, weil ich jede „Ebene überprüfen "des Namensraums.

Gibt es einen empfohlenen Weg, dies zu tun?

+0

Ich hatte fast die gleiche Frage, aber allgemeiner: Wie überprüft man, ob ein Ausdruck mit einem bestimmten Typ übereinstimmt, nicht mit einem bestimmten Typ wie in dieser Frage. [Siehe meine Antwort] (http://stackoverflow.com/a/33994426/3568661) mit voller Codebeispiel hier –

Antwort

6

Überprüfen Sie, ob der Typ is a generic type und, wenn dies der Fall ist, OriginalDefinition verwenden, um den unkonstruierten generischen Typ zurückzugeben.

+1

Danke! Ich hatte die Tatsache übersehen, dass die 'ITypeInfo', die ich bekam, tatsächlich ein 'INamedTypeSymbol' war, so dass ich die 'IsGeneric'-Eigenschaft nicht sehen konnte. Aber 'ConstructUnboundGenericType' gibt mir' Task <> ', anstatt' Task ', so dass es nicht mit dem Typ übereinstimmt, den ich mit' GetTypeFromMetadataName 'bekomme. Ich musste stattdessen die Eigenschaft ['ConstructedFrom'] (http://source.roslyn.io/#Microsoft.CodeAnalysis/Symbols/INamedTypeSymbol.cs2b034eb9d8cd5598) verwenden. –

+2

Verwenden Sie 'OriginalDefinition' - Sie erhalten den Typ, der in allen Fällen mit GetTypeByMetadataName übereinstimmt. In geschachtelten generischen oder generischen Methodenfällen ist ConstructedFrom nicht ganz das, was Sie wollen. –

+0

@JasonMalinowski, danke! –