| | | 1 | | // ----------------------------------------------------------------------- |
| | | 2 | | // <copyright file="EnumExtensions.cs" company="Stéphane ANDRE"> |
| | | 3 | | // Copyright (c) Stéphane ANDRE. All rights reserved. |
| | | 4 | | // </copyright> |
| | | 5 | | // ----------------------------------------------------------------------- |
| | | 6 | | |
| | | 7 | | using System; |
| | | 8 | | using System.Collections.Generic; |
| | | 9 | | using System.Globalization; |
| | | 10 | | using System.Linq; |
| | | 11 | | using MyNet.Primitives; |
| | | 12 | | |
| | | 13 | | #pragma warning disable IDE0130 // Namespace does not match folder structure |
| | | 14 | | namespace MyNet.Observable; |
| | | 15 | | #pragma warning restore IDE0130 // Namespace does not match folder structure |
| | | 16 | | |
| | | 17 | | /// <summary> |
| | | 18 | | /// Builds localized item lists for system enums and smart enums. |
| | | 19 | | /// </summary> |
| | | 20 | | public static class EnumExtensions |
| | | 21 | | { |
| | | 22 | | extension(Type type) |
| | | 23 | | { |
| | | 24 | | /// <summary> |
| | | 25 | | /// Creates a list of <see cref="LocalizedEnum"/> values for a system enum type. |
| | | 26 | | /// </summary> |
| | | 27 | | /// <param name="excludedValues">Optional enum values to exclude from the result.</param> |
| | | 28 | | /// <returns>A localized item for each enum member.</returns> |
| | | 29 | | public IList<LocalizedEnum> GetLocalizedEnums(IEnumerable<object>? excludedValues = null) |
| | | 30 | | { |
| | 18 | 31 | | ArgumentNullException.ThrowIfNull(type); |
| | | 32 | | |
| | 15 | 33 | | if (!type.IsEnum) |
| | | 34 | | { |
| | 3 | 35 | | throw new ArgumentException($"Type '{type.FullName}' is not a system enum."); |
| | | 36 | | } |
| | | 37 | | |
| | 12 | 38 | | var excludedList = excludedValues?.ToList(); |
| | 12 | 39 | | if (excludedList is not null) |
| | | 40 | | { |
| | 6 | 41 | | ValidateExcludedValues(type, excludedList); |
| | | 42 | | } |
| | | 43 | | |
| | 9 | 44 | | return [.. Enum.GetValues(type) |
| | 9 | 45 | | .Cast<Enum>() |
| | 9 | 46 | | .Where(x => excludedList?.Contains(x) != true) |
| | 9 | 47 | | .Select(x => new LocalizedEnum(x))]; |
| | | 48 | | } |
| | | 49 | | |
| | | 50 | | /// <summary> |
| | | 51 | | /// Creates a list of <see cref="LocalizedSmartEnum"/> values for a smart enum type. |
| | | 52 | | /// </summary> |
| | | 53 | | /// <param name="excludedValues">Optional smart enum values to exclude from the result.</param> |
| | | 54 | | /// <returns>A localized item for each smart enum member.</returns> |
| | | 55 | | public IList<LocalizedSmartEnum> GetLocalizedSmartEnums(IEnumerable<object>? excludedValues = null) |
| | | 56 | | { |
| | 12 | 57 | | ArgumentNullException.ThrowIfNull(type); |
| | | 58 | | |
| | 12 | 59 | | if (!typeof(ISmartEnum).IsAssignableFrom(type)) |
| | | 60 | | { |
| | 3 | 61 | | throw new ArgumentException( |
| | 3 | 62 | | $"Type '{type.FullName}' does not implement {nameof(ISmartEnum)}."); |
| | | 63 | | } |
| | | 64 | | |
| | 9 | 65 | | var excludedList = excludedValues?.ToList(); |
| | 9 | 66 | | if (excludedList is not null) |
| | | 67 | | { |
| | 6 | 68 | | ValidateExcludedValues(type, excludedList); |
| | | 69 | | } |
| | | 70 | | |
| | 6 | 71 | | return [.. SmartEnumSource.GetAll(type) |
| | 6 | 72 | | .Where(x => excludedList?.Contains(x) != true) |
| | 6 | 73 | | .Select(x => new LocalizedSmartEnum(x))]; |
| | | 74 | | } |
| | | 75 | | } |
| | | 76 | | |
| | | 77 | | /// <summary> |
| | | 78 | | /// Creates a list of <see cref="LocalizedEnum{TEnum}"/> values for a system enum type. |
| | | 79 | | /// </summary> |
| | | 80 | | /// <typeparam name="TEnum">The enum type.</typeparam> |
| | | 81 | | /// <param name="excludedValues">Optional enum values to exclude from the result.</param> |
| | | 82 | | /// <returns>A localized item for each enum member.</returns> |
| | | 83 | | public static IList<LocalizedEnum<TEnum>> GetLocalizedEnums<TEnum>(IEnumerable<TEnum>? excludedValues = null) |
| | | 84 | | where TEnum : struct, Enum |
| | 6 | 85 | | => [.. Enum.GetValues<TEnum>() |
| | 6 | 86 | | .Where(x => excludedValues?.Contains(x) != true) |
| | 6 | 87 | | .Select(x => new LocalizedEnum<TEnum>(x))]; |
| | | 88 | | |
| | | 89 | | /// <summary> |
| | | 90 | | /// Creates a list of <see cref="LocalizedSmartEnum{TSmartEnum}"/> values for a smart enum type. |
| | | 91 | | /// </summary> |
| | | 92 | | /// <typeparam name="TSmartEnum">The smart enum type.</typeparam> |
| | | 93 | | /// <param name="excludedValues">Optional smart enum values to exclude from the result.</param> |
| | | 94 | | /// <returns>A localized item for each smart enum member.</returns> |
| | | 95 | | public static IList<LocalizedSmartEnum<TSmartEnum>> GetLocalizedSmartEnums<TSmartEnum>( |
| | | 96 | | IEnumerable<TSmartEnum>? excludedValues = null) |
| | | 97 | | where TSmartEnum : class, ISmartEnum |
| | 6 | 98 | | => [.. SmartEnumSource.GetAll<TSmartEnum>() |
| | 6 | 99 | | .Where(x => excludedValues?.Contains(x) != true) |
| | 6 | 100 | | .Select(x => new LocalizedSmartEnum<TSmartEnum>(x))]; |
| | | 101 | | |
| | | 102 | | /// <summary> |
| | | 103 | | /// Validates excluded values against the expected enum or smart enum type. |
| | | 104 | | /// </summary> |
| | | 105 | | /// <param name="enumType">The enum or smart enum type.</param> |
| | | 106 | | /// <param name="excludedValues">The values to validate.</param> |
| | | 107 | | /// <exception cref="ArgumentNullException">Thrown when an argument is null.</exception> |
| | | 108 | | /// <exception cref="ArgumentException">Thrown when an excluded value has an invalid type.</exception> |
| | | 109 | | private static void ValidateExcludedValues(Type enumType, IEnumerable<object> excludedValues) |
| | | 110 | | { |
| | 12 | 111 | | ArgumentNullException.ThrowIfNull(enumType); |
| | 12 | 112 | | ArgumentNullException.ThrowIfNull(excludedValues); |
| | | 113 | | |
| | 12 | 114 | | var invalidType = enumType.IsEnum |
| | 12 | 115 | | ? excludedValues |
| | 12 | 116 | | .Select(v => Nullable.GetUnderlyingType(v.GetType()) ?? v.GetType()) |
| | 12 | 117 | | .FirstOrDefault(e => !e.IsEnum || e != enumType) |
| | 12 | 118 | | : excludedValues |
| | 12 | 119 | | .Select(v => v.GetType()) |
| | 12 | 120 | | .FirstOrDefault(e => e != enumType && !enumType.IsAssignableFrom(e)); |
| | | 121 | | |
| | 12 | 122 | | if (invalidType != null) |
| | | 123 | | { |
| | 6 | 124 | | throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Wrong type : {0}", invalidType.Name |
| | | 125 | | } |
| | 6 | 126 | | } |
| | | 127 | | } |
| | | 128 | | |