如何在C#源代码生成器中检测数组类型并获取其元素类型?
问题描述
我正在编写一个处理模型类的C#源代码生成器,用于为类添加自定义序列化代码。模型类包含多种属性类型,当前我需要处理数组类型的属性,但无法检测这类属性:能看到属性名称和类似string[]的类型,其基类为System.Array,但无法获取元素类型。
针对集合类型,我已实现如下检测方法:
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; }
我尝试按如下方式检测数组,但数组并非泛型类型,无法找到元素类型:
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; }
请问数组类型的元素类型该从何处获取?
解决方案
数组类型在Roslyn的符号系统中对应的是**IArrayTypeSymbol**,而非INamedTypeSymbol,你需要直接判断类型符号是否实现该接口,再通过它的ElementType属性获取元素类型。
修改后的TryGetArrayItemType方法如下:
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; }
额外说明
IArrayTypeSymbol是Roslyn专门用于表示数组类型的符号接口,ElementType属性直接返回数组元素的类型符号,无需通过基类间接获取。- 若需处理多维数组,可通过
IArrayTypeSymbol.Rank属性获取数组的维度数。
你也可以考虑将集合与数组的检测逻辑合并为一个通用方法(比如TryGetEnumerableItemType),统一处理可枚举类型的元素类型获取。
内容的提问来源于stack exchange,提问作者ygoe
相关产品推荐
相关产品推荐

