< Summary - PropertyGridHelpers Code Coverage

Information
Class: PropertyGridHelpers.Converters.EnumTextConverter
Assembly: PropertyGridHelpers
File(s): c:\agent\_work\9\s\Code\PropertyGridHelpers\Converters\EnumTextConverter.cs
Tag: PropertyGridHelpers Build_2025.7.15.1_#485
Line coverage
100%
Covered lines: 63
Uncovered lines: 0
Coverable lines: 63
Total lines: 189
Line coverage: 100%
Branch coverage
100%
Covered branches: 44
Total branches: 44
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBlocks covered Blocks not covered Branch coverage Crap Score Cyclomatic complexity Line coverage
EnumTextConverter(...)20----
.ctor(...)--100%11100%
CanConvertTo(...)120----
CanConvertTo(...)--100%44100%
ConvertTo(...)310----
ConvertTo(...)--100%1212100%
ConvertTo(...)300----
CanConvertFrom(...)80----
CanConvertFrom(...)--100%22100%
ConvertFrom(...)530----
ConvertFrom(...)--100%2020100%
ConvertFrom(...)460----
GetStandardValues(...)150100%66100%
GetStandardValues(...)130----

File(s)

c:\agent\_work\9\s\Code\PropertyGridHelpers\Converters\EnumTextConverter.cs

#LineLine coverage
 1using PropertyGridHelpers.Attributes;
 2using System;
 3using System.ComponentModel;
 4using System.Globalization;
 5using System.Linq;
 6using System.Reflection;
 7using static System.ComponentModel.TypeConverter;
 8
 9namespace PropertyGridHelpers.Converters
 10{
 11    /// <summary>
 12    /// Provides a type converter for enums that supports displaying custom user-friendly
 13    /// text for enum fields using the <see cref="EnumTextAttribute"/> or
 14    /// <see cref="LocalizedEnumTextAttribute"/>.
 15    /// </summary>
 16    /// <remarks>
 17    /// This converter allows enum values to be shown in a property grid or dropdown list
 18    /// with more readable labels instead of their default names. For localization or
 19    /// specialized labeling, decorate the enum fields with <see cref="EnumTextAttribute"/>
 20    /// or <see cref="LocalizedEnumTextAttribute"/>.
 21    /// </remarks>
 22    /// <example>
 23    /// <code>
 24    /// public enum Status
 25    /// {
 26    ///     [EnumText("Pending Approval")]
 27    ///     Pending,
 28    ///     [EnumText("Approved")]
 29    ///     Approved,
 30    ///     [EnumText("Rejected")]
 31    ///     Rejected
 32    /// }
 33    ///
 34    /// [TypeConverter(typeof(EnumTextConverter))]
 35    /// public Status Status { get; set; }
 36    /// </code>
 37    /// </example>
 38    /// <seealso cref="EnumConverter"/>
 39    public partial class EnumTextConverter : EnumConverter
 40    {
 41        /// <summary>
 42        /// Initializes a new instance of the <see cref="EnumTextConverter"/> class
 43        /// for the given enum type.
 44        /// </summary>
 45        /// <param name="type">The target enum type to convert.</param>
 46        /// <exception cref="ArgumentNullException">Thrown if <paramref name="type"/> is null.</exception>
 37647        public EnumTextConverter(Type type) : base(type) { }
 48
 49        /// <inheritdoc/>
 50        /// <remarks>
 51        /// Supports conversion to <see cref="string"/> or <see cref="int"/> representations.
 52        /// </remarks>
 53        public override bool CanConvertTo(
 54            ITypeDescriptorContext context,
 55            Type destinationType) =>
 3656            destinationType is null
 3657                ? throw new ArgumentNullException(nameof(destinationType))
 3658                : destinationType == typeof(string) || destinationType == typeof(int);
 59
 60        /// <summary>
 61        /// Converts the specified enum value to a <see cref="string"/> or <see cref="int"/>
 62        /// based on the requested destination type.
 63        /// </summary>
 64        /// <param name="context">An optional format context.</param>
 65        /// <param name="culture">Culture information for the conversion.</param>
 66        /// <param name="value">The value to convert, expected to be an enum of the specified type.</param>
 67        /// <param name="destinationType">The target type for conversion (string or int).</param>
 68        /// <returns>The converted value, or <c>null</c> if the input is <c>null</c>.</returns>
 69        /// <exception cref="ArgumentException">
 70        /// Thrown if <paramref name="value"/> is not of the expected enum type, or
 71        /// if the destination type is unsupported.
 72        /// </exception>
 73        public override object ConvertTo(
 74            ITypeDescriptorContext context,
 75            CultureInfo culture,
 76            object value,
 77            Type destinationType)
 16478        {
 18479            if (value == null) return null;
 16080            if (value.GetType() != EnumType)
 2081                throw new ArgumentException($"value is expected to be of type {EnumType}.", nameof(value));
 15682            if (destinationType == typeof(string))
 13683            {
 84                string results;
 14485                Attribute dna = LocalizedEnumTextAttribute.Get((Enum)value);
 14486                if (dna == null)
 11687                {
 12488                    dna = EnumTextAttribute.Get((Enum)value);
 12489                    results = dna == null
 12490                        ? value.ToString()
 12491                        : ((EnumTextAttribute)dna).EnumText;
 11692                }
 93                else
 3694                    results = ((LocalizedEnumTextAttribute)dna).GetLocalizedText(context, culture, EnumType);
 95
 14496                return results;
 97            }
 2898            else if (destinationType == typeof(int))
 2499                return (int)value;
 20100            return null;
 160101        }
 102
 103        /// <inheritdoc/>
 104        /// <remarks>
 105        /// Supports conversion from <see cref="string"/> or <see cref="int"/> to the target enum.
 106        /// </remarks>
 107        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) =>
 24108            sourceType == typeof(string) || sourceType == typeof(int);
 109
 110        /// <summary>
 111        /// Converts from a string or integer to the corresponding enum value.
 112        /// </summary>
 113        /// <param name="context">An optional format context.</param>
 114        /// <param name="culture">Culture information for the conversion.</param>
 115        /// <param name="value">The string or integer to convert.</param>
 116        /// <returns>The parsed enum value.</returns>
 117        /// <exception cref="ArgumentException">
 118        /// Thrown if <paramref name="value"/> is neither a string nor an int, or cannot be parsed.
 119        /// </exception>
 120        public override object ConvertFrom(
 121            ITypeDescriptorContext context,
 122            CultureInfo culture,
 123            object value)
 60124        {
 76125            if (value == null) return null;
 60126            if (value is string stringValue)
 32127            {
 260128                foreach (var fi in EnumType.GetFields(BindingFlags.Public | BindingFlags.Static))
 100129                {
 130                    // 1. Check LocalizedEnumTextAttribute
 108131                    var localized = LocalizedEnumTextAttribute.Get(fi);
 108132                    if (localized != null)
 24133                    {
 32134                        var localizedText = localized.GetLocalizedText(context, culture, EnumType);
 32135                        if (string.Equals(stringValue, localizedText, StringComparison.Ordinal))
 20136                            return Enum.Parse(EnumType, fi.Name);
 20137                    }
 138
 139                    // 2. Check EnumTextAttribute
 104140                    var dna = EnumTextAttribute.Get(fi);
 141
 104142                    if ((dna != null) && (string.Equals((string)value, dna.EnumText, StringComparison.Ordinal)))
 24143                        return Enum.Parse(EnumType, fi.Name);
 88144                }
 145
 28146                if (Enum.GetNames(EnumType).Contains(value))
 20147                    return Enum.Parse(EnumType, (string)value);
 148                else
 16149                {
 24150                    var enums = Enum.GetValues(EnumType);
 24151                    return enums.GetValue(0);
 152                }
 153            }
 36154            else if (value is int intValue)
 20155            {
 28156                var s = Enum.GetName(EnumType, intValue);
 28157                var e = Enum.Parse(EnumType, s);
 28158                return e;
 159            }
 160
 24161            throw new ArgumentException("The value is expected to be a string or an int.", nameof(value));
 52162        }
 163
 164        #region GetStandardValues ^^^^^^^^^^^^^^^^^^^^^^^^^
 165
 166        /// <summary>
 167        /// Returns a collection of standard enum values for the associated type.
 168        /// </summary>
 169        /// <param name="context">A type descriptor context providing information about the component.</param>
 170        /// <returns>
 171        /// A <see cref="StandardValuesCollection"/> containing the enum values, or the base
 172        /// implementation if no enum type is detected.
 173        /// </returns>
 174        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
 24175        {
 176            // Return all enum values for the property
 32177            if (context?.PropertyDescriptor != null)
 16178            {
 24179                var enumType = context.PropertyDescriptor.PropertyType;
 24180                if (enumType.IsEnum)
 20181                    return new StandardValuesCollection(Enum.GetValues(enumType));
 12182            }
 183
 28184            return base.GetStandardValues(context);
 24185        }
 186
 187        #endregion
 188    }
 189}