使用Roslyn,如何确定ITypeSymbol
是否是原始类型?
ITypeSymbol
没有像IsPrimitive
Type.IsPrimitive
属性
有没有办法将ITypeSymbol
转换为Type或其他方式来确定ITypeSymbol
是否是原始类型?
答案 0 :(得分:1)
类型是否是原始类型取决于您的语言。在C#中,DateTime不是原始的,而是在VB中。由于ITypeSymbol用于两种语言,因此它没有特定于语言的属性。
答案 1 :(得分:0)
尝试以下扩展方法:
//eg: symbol.IsFullNameEquals("List`1", "Generic", "Collections", "System")
internal static bool IsFullNameEquals(this ISymbol symbol, params string[] nameParts) {
if (symbol == null) throw new ArgumentNullException("symbol");
if (nameParts == null || nameParts.Length == 0) throw new ArgumentNullException("nameParts");
var idx = 0;
for (; symbol != null; symbol = symbol.ContainingSymbol) {
var name = symbol.MetadataName;
if (string.IsNullOrEmpty(name)) break;
if (idx == nameParts.Length) return false;
if (name != nameParts[idx]) return false;
idx++;
}
return idx == nameParts.Length;
}
//eg: var idx = symbol.MatchFullName(new []{"List`1", "Dictionary`2"}, new []{"Generic", "Collections", "System"});
//return value: -1: none; 0: symbol is List`1; 1: symbol is Dictionary`2
internal static int MatchFullName(this ISymbol symbol, string[] typeNames, string[] outerNameParts) {
if (symbol == null) throw new ArgumentNullException("symbol");
if (typeNames == null || typeNames.Length == 0) throw new ArgumentNullException("typeNames");
var fullLength = 1 + (outerNameParts != null ? outerNameParts.Length : 0);
int idx = 0, result = -1;
for (; symbol != null; symbol = symbol.ContainingSymbol) {
var name = symbol.MetadataName;
if (string.IsNullOrEmpty(name)) break;
if (idx == fullLength) return -1;
if (idx == 0) {
for (var i = 0; i < typeNames.Length; i++) {
if (name == typeNames[i]) {
result = i;
break;
}
}
if (result == -1) return -1;
}
else {
if (name != outerNameParts[idx - 1]) return -1;
}
idx++;
}
if (idx == fullLength) return result;
return -1;
}
答案 2 :(得分:0)
看起来代码确定它位于TypedConstant class,但它是内部的,我找不到能够很好地帮助我的公共API。我最终将方法复制到我的项目中。
/// <remarks>
/// TypedConstant isn't computing its own kind from the type symbol because it doesn't
/// have a way to recognize the well-known type System.Type.
/// </remarks>
internal static TypedConstantKind GetTypedConstantKind(ITypeSymbol type, Compilation compilation)
{
Debug.Assert(type != null);
switch (type.SpecialType)
{
case SpecialType.System_Boolean:
case SpecialType.System_SByte:
case SpecialType.System_Int16:
case SpecialType.System_Int32:
case SpecialType.System_Int64:
case SpecialType.System_Byte:
case SpecialType.System_UInt16:
case SpecialType.System_UInt32:
case SpecialType.System_UInt64:
case SpecialType.System_Single:
case SpecialType.System_Double:
case SpecialType.System_Char:
case SpecialType.System_String:
case SpecialType.System_Object:
return TypedConstantKind.Primitive;
default:
switch (type.TypeKind)
{
case TypeKind.Array:
return TypedConstantKind.Array;
case TypeKind.Enum:
return TypedConstantKind.Enum;
case TypeKind.Error:
return TypedConstantKind.Error;
}
if (compilation != null &&
compilation.IsSystemTypeReference(type))
{
return TypedConstantKind.Type;
}
return TypedConstantKind.Error;
}
}