Пример #1
0
        /// <summary>
        /// 将一个或多个枚举常数的名称、描述或数字值的字符串表示转换成等效的枚举对象。
        /// 一个参数指定该操作是否区分大小写。
        /// </summary>
        /// <param name="enumType">枚举类型。</param>
        /// <param name="value">包含要转换的值或名称的字符串。</param>
        /// <param name="ignoreCase">若要忽略大小写则为 <c>true</c>;
        /// 否则为 <c>false</c>。</param>
        /// <returns><paramref name="enumType"/> 类型的对象,其值由 <paramref name="value"/> 表示。</returns>
        /// <exception cref="System.ArgumentNullException">
        /// <paramref name="value"/> 为 <c>null</c>。</exception>
        /// <exception cref="System.ArgumentException">
        /// <paramref name="enumType"/> 不是 <see cref="System.Enum"/>。</exception>
        /// <exception cref="System.ArgumentException">
        /// <paramref name="value"/> 是空字符串 ("") 或只包含空白。</exception>
        /// <exception cref="System.ArgumentException">
        /// <paramref name="value"/> 是一个名称,但不是为该枚举定义的命名常量之一。</exception>
        /// <exception cref="System.OverflowException">
        /// <paramref name="value"/> 超出 <paramref name="enumType"/>
        /// 基础类型的范围。</exception>
        public static object ParseEx(Type enumType, string value, bool ignoreCase)
        {
            ExceptionHelper.CheckArgumentNull(enumType, "enumType");
            ExceptionHelper.CheckArgumentNull(value, "value");
            if (!enumType.IsEnum)
            {
                throw ExceptionHelper.MustBeEnum("enumType", enumType);
            }
            value = value.Trim();
            if (value.Length == 0)
            {
                throw ExceptionHelper.MustContainEnumInfo("value");
            }
            // 尝试对数字进行解析,这样可避免之后的字符串比较。
            ulong tmpValue;

            if (ParseString(value, out tmpValue))
            {
                return(Enum.ToObject(enumType, tmpValue));
            }
            // 尝试对描述信息进行解析。
            EnumCache        cache      = GetEnumCache(enumType);
            StringComparison comparison = ignoreCase ?
                                          StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
            ulong valueUL = 0;
            int   start   = 0;

            do
            {
                // 去除前导空白。
                while (char.IsWhiteSpace(value, start))
                {
                    start++;
                }
                int idx = value.IndexOf(',', start);
                if (idx < 0)
                {
                    idx = value.Length;
                }
                int nIdx = idx - 1;
                // 去除后面的空白。
                while (char.IsWhiteSpace(value, nIdx))
                {
                    nIdx--;
                }
                if (nIdx >= start)
                {
                    string str = value.Substring(start, nIdx - start + 1);
                    int    j   = 0;
                    // 比较常数值的名称和描述信息,先比较名称,后比较描述信息。
                    for (; j < cache.Names.Length; j++)
                    {
                        if (string.Equals(str, cache.Names[j], comparison))
                        {
                            // 与常数值匹配。
                            valueUL |= cache.Values[j];
                            break;
                        }
                    }
                    if (j == cache.Names.Length && cache.HasDescription)
                    {
                        // 比较描述信息。
                        for (j = 0; j < cache.Descriptions.Length; j++)
                        {
                            if (string.Equals(str, cache.Descriptions[j], comparison))
                            {
                                // 与描述信息匹配。
                                valueUL |= cache.Values[j];
                                break;
                            }
                        }
                    }
                    // 未识别的枚举值。
                    if (j == cache.Descriptions.Length)
                    {
                        // 尝试识别为数字。
                        if (ParseString(str, out tmpValue))
                        {
                            valueUL |= tmpValue;
                        }
                        else
                        {
                            // 不能识别为数字。
                            throw ExceptionHelper.EnumValueNotFound(enumType, str);
                        }
                    }
                }
                start = idx + 1;
            } while (start < value.Length);
            return(Enum.ToObject(enumType, valueUL));
        }