I'm writing a source generator that processes my model classes and adds some custom serialisation code for them. The model classes can have all sorts of property types. I'm currently interested in the array properties. I cannot detect them. I see their name and the type as something like "string[]" and the base type is System.Array but I need to know the item type as well.
For collection types, the check is:
public static bool TryGetCollectionItemType(this ITypeSymbol typeSymbol, out ITypeSymbol? itemType)
{
if (typeSymbol is INamedTypeSymbol namedType &&
namedType.AllInterfaces
.SingleOrDefault(i =>
i.IsGenericType &&
i.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)
.StartsWith("global::System.Collections.Generic.ICollection<"))
is INamedTypeSymbol collectionType)
{
var typeArguments = namedType.TypeArguments;
Debug.Assert(typeArguments.Length == 1);
itemType = typeArguments[0];
return itemType.TypeKind != TypeKind.Error;
}
itemType = null;
return false;
}
Currently I'm trying to detect an array like this, but it doesn't seem to be generic. I can't find the item type anywhere.
public static bool TryGetArrayItemType(this ITypeSymbol typeSymbol, out ITypeSymbol? itemType)
{
if (typeSymbol is INamedTypeSymbol namedType &&
namedType.BaseType?.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) == "global::System.Array" &&
namedType.BaseType.IsGenericType) // it's not generic
{
var typeArguments = namedType.BaseType.TypeArguments;
Debug.Assert(typeArguments.Length == 1);
itemType = typeArguments[0]; // where can I find this instead?
return itemType.TypeKind != TypeKind.Error;
}
itemType = null;
return false;
}
Where is the item type of the array type?
I found out how this can be done. The ITypeSymbol
has other derivations as well, including IArrayTypeSymbol
. This lets me access the item type, actually quite easily:
public static bool TryGetArrayItemType(this ITypeSymbol typeSymbol, out ITypeSymbol? itemType)
{
if (typeSymbol is IArrayTypeSymbol arrayType)
{
itemType = arrayType.ElementType;
return itemType.TypeKind != TypeKind.Error;
}
itemType = null;
return false;
}