I have successfully received an ITypeSymbol from a SyntaxNode by using:
SemanticModel.GetTypeInfo(sytaxNode).ConvertedType
Now I would like to know if this ITypeSymbol
corresponds to a System.Type
instance that is present in my executing code, like typeof(IEnumerable<int>)
or someObject.GetType()
.
I tried
typeInfo.ConvertedType.ToString() == type.ToString()
But these do not use the same formatting rules, for instance for generics like IEnumerable<int>
TypeInfo.ToString() == "System.Collections.Generic.IEnumerable<int>"
while
typeof(IEnumerable<int>).ToString() == "System.Collections.Generic.IEnumerable`1[System.Int32]"
Moreover I think it would be better to compare AssemblyQualifiedNames in stead of just the Namespace and type name to avoid possible name clashes.
Ideally I would like to be able to get the actual System.Type instance in my executing code that corresponds to the ITypeInfo I got from the semantic model (provided that the required assembly is loaded and/or available). That would allow checking if the type is assignable from some other type etc.
You can get the INamedTypeSymbol
for a type name with Compilation.GetTypeByMetadataName()
.
So try this:
semanticModel.GetTypeInfo(sytaxNode).ConvertedType.Equals(
semanticModel.Compilation.GetTypeByMetadataName(typeof(WhateverType).FullName))
This won't work with closed generic types, for those you'll need to do a bit more. For example:
var ienumerableType = semanticModel.Compilation.GetTypeByMetadataName("System.Collections.Generic.IEnumerable`1");
var intType = semanticModel.Compilation.GetTypeByMetadataName("System.Int32");
var type = ienumerableType.Construct(intType);
Based on the answer from @Tamas, I created the following recursive solution that works for closed generic types.
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>());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With