简体   繁体   English

使用roslyn确定原始类型

[英]Determine primitive types using roslyn

Using Roslyn, how to determine whether an ITypeSymbol is a primitive type or not? 使用Roslyn,如何确定ITypeSymbol是否是原始类型?

The ITypeSymbol does not have the IsPrimitive property like Type.IsPrimitive ITypeSymbol没有像Type.IsPrimitive这样的IsPrimitive属性

Is there a way to convert ITypeSymbol to Type or some other way to determine whether an ITypeSymbol is a primitive type? 有没有办法将ITypeSymbol转换为Type或其他一些方法来确定ITypeSymbol是否是原始类型?

Whether a type is primitive or not depends on your language. 类型是否是原始类型取决于您的语言。 In C# DateTime is not a primitive, but it is in VB. 在C#中,DateTime不是原始的,而是在VB中。 Since ITypeSymbol is used for both languages, it does not have language-specific properties. 由于ITypeSymbol用于两种语言,因此它没有特定于语言的属性。

Try the following extension methods: 请尝试以下扩展方法:

    //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;
    }

Looks like the code to determine that is in the TypedConstant class , but it is internal and I couldn't find a public API that would nicely get me there. 看起来像确定它在TypedConstant类中的代码 ,但它是内部的,我找不到一个很好地让我在那里的公共API。 I ended up copying the method into to my project. 我最终将方法复制到我的项目中。

    /// <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;
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM