/// <summary> /// 将一个或多个枚举常数的名称、描述或数字值的字符串表示转换成等效的枚举值。 /// 一个参数指定该操作是否区分大小写。 /// </summary> /// <param name="enumType">枚举类型。</param> /// <param name="value">包含要转换的值或名称的字符串。</param> /// <param name="ignoreCase">若要忽略大小写则为 <c>true</c>;否则为 <c>false</c>。</param> /// <returns><see cref="ulong"/> 表示的枚举值。</returns> /// <exception cref="ArgumentException"><paramref name="value"/> 是空字符串 ("") 或只包含空白。</exception> /// <exception cref="ArgumentException"><paramref name="value"/> 是一个名称,但不是为该枚举定义的命名常量之一。 /// </exception> /// <exception cref="OverflowException"><paramref name="value"/> 超出 <paramref name="enumType"/> /// 基础类型的范围。</exception> private static ulong ParseToULong(Type enumType, string value, bool ignoreCase) { Contract.Requires(enumType != null && enumType.IsEnum); Contract.Requires(value != null); value = value.Trim(); if (value.Length == 0) { throw CommonExceptions.MustContainValidInfo("value"); } // 尝试对数字进行解析,这样可避免之后的字符串比较。 ulong tmpValue; if (TryParseString(value, out tmpValue)) { return(tmpValue); } // 尝试对描述信息进行解析。 EnumCache cache = GetEnumCache(enumType); StringComparison comparison = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; ulong ulValue = 0UL; int start = 0; do { // 去除前导空白。 while (char.IsWhiteSpace(value, start)) { start++; } int idx = value.IndexOf(',', start); if (idx < 0) { idx = value.Length; } if (idx == start) { start = idx + 1; continue; } int nIdx = idx - 1; // 去除后面的空白。 while (char.IsWhiteSpace(value, nIdx)) { nIdx--; } Contract.Assume(nIdx >= start); string str = value.Substring(start, nIdx - start + 1); start = idx + 1; // 尝试识别为名称、描述或数字。 if (!TryParseString(str, cache, comparison, ref tmpValue) && !TryParseString(str, out tmpValue)) { throw CommonExceptions.EnumValueNotFound(enumType, str); } ulValue |= tmpValue; } while (start < value.Length); return(ulValue); }
/// <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) { CommonExceptions.CheckArgumentNull(enumType, "enumType"); CommonExceptions.CheckArgumentNull(value, "value"); if (!enumType.IsEnum) { throw CommonExceptions.MustBeEnum("enumType", enumType); } value = value.Trim(); if (value.Length == 0) { throw CommonExceptions.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 CommonExceptions.EnumValueNotFound(enumType, str); } } } start = idx + 1; } while (start < value.Length); return(Enum.ToObject(enumType, valueUL)); }