2
0

EnumUtils.cs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. using System.Globalization;
  2. namespace MeloongCore;
  3. public static class EnumUtils {
  4. /// <summary>
  5. /// 获取枚举的所有值。
  6. /// </summary>
  7. private static IEnumerable<T> GetAllValues<T>() where T : struct, Enum
  8. => Enum.GetValues(typeof(T)).Cast<T>();
  9. /// <summary>
  10. /// 将字符串转换为枚举。
  11. /// 支持枚举名或枚举序数;若为空字符串或 <see langword="null"/> 则返回 0。
  12. /// 转换失败会抛出异常。
  13. /// </summary>
  14. public static T FromString<T>(string? value) where T : struct, Enum {
  15. if (string.IsNullOrEmpty(value)) {
  16. return (T) Enum.ToObject(typeof(T), 0);
  17. } else if (double.TryParse(value, NumberStyles.Float, CultureInfo.CurrentCulture, out var number)) {
  18. return (T) Enum.ToObject(typeof(T), Convert.ToInt64(number));
  19. } else {
  20. return (T) Enum.Parse(typeof(T), value, true);
  21. }
  22. }
  23. /// <summary>
  24. /// 对于具有 <see cref="FlagsAttribute"/> 的枚举,返回其所有 Flag 值。
  25. /// 建议仅对没有极端值的正数枚举使用。
  26. /// </summary>
  27. /// <remarks>
  28. /// 会跳过:0、非 2 的幂的值、不在枚举值中的数、组合值、对应同一个枚举项的多个别名。
  29. /// </remarks>
  30. public static List<T> GetAllFlags<T>() where T : struct, Enum {
  31. if (allFlagsCache.TryGetValue(typeof(T), out var cached)) return cached.Cast<T>().ToList();
  32. if (!typeof(T).IsDefined(typeof(FlagsAttribute), inherit: false)) throw new ArgumentException($"枚举 {typeof(T).FullName} 没有定义 FlagsAttribute。");
  33. var flags = new List<T>();
  34. foreach (var element in EnumUtils.GetAllValues<T>().Distinct()) {
  35. var number = Convert.ToInt64(element, CultureInfo.InvariantCulture);
  36. if (number == 0 || (number & (number - 1)) != 0) continue; // 跳过 0 和非 2 的幂的值
  37. flags.Add(element);
  38. }
  39. allFlagsCache[typeof(T)] = flags.Cast<Enum>().ToList();
  40. return flags;
  41. }
  42. private static readonly ConcurrentDictionary<Type, List<Enum>> allFlagsCache = new();
  43. }