using System; using System.ComponentModel; namespace ConsoleApplication1 { public enum ThreadPriority { [Description("Highest")] Highest, [Description("Above Normal")] AboveNormal, [Description("Normal")] Normal, [Description("Below Normal")] BelowNormal, [Description("Lowest")] Lowest } class Program { static void Main(string[] args) { ThreadPriority threadPriority = EnumHelper<ThreadPriority>.Parse("AboveNormal"); System.Diagnostics.Debug.Assert(threadPriority == ThreadPriority.AboveNormal); string description = EnumHelper<ThreadPriority>.EnumValueDescription(threadPriority); System.Diagnostics.Debug.Assert(description.Equals("Above Normal")); threadPriority = EnumHelper<ThreadPriority>.ParseOrDescriptionMatch("Below Normal", ThreadPriority.Normal); System.Diagnostics.Debug.Assert(threadPriority == ThreadPriority.BelowNormal); if (!EnumHelper<ThreadPriority>.TryParse("Highest", out threadPriority)) { System.Diagnostics.Debug.Fail("TryParse expected to succeed"); } System.Diagnostics.Debug.Assert(threadPriority == ThreadPriority.Highest); if (EnumHelper<ThreadPriority>.TryParse("Foo Bar", out threadPriority)) { System.Diagnostics.Debug.Fail("TryParse expected to fail"); } } } public static class EnumHelper<T> where T : struct, IComparable, IFormattable, IConvertible { ////// Static constructor to ensure T is an enum /// static EnumHelper() { if (!typeof(T).IsEnum) { throw new ArgumentException("Type parameter must be an enum"); } } /// <summary> /// Converts the string representation of the name or numeric value of one or /// more enumerated constants to an equivalent enumerated object. /// </summary> /// <param name="value">A string containing the name or value to convert.</param> /// <returns>An object of type T whose value is represented by value.</returns> /// <exception cref="System.ArgumentNullException">value is null</exception> /// <exception cref="System.ArgumentException">value is either an empty string or /// only contains white space. -or- value is a name, but not one of the named /// constants defined for the enumeration. ///</exception> public static T Parse(string value) { return (T)Enum.Parse(typeof(T), value); } ////// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object. /// /// A string containing the name or value to convert. /// When this method returns, contains the object of type T whose /// value is represented by the value, if the conversion succeeded, or the first /// value in the enum if conversion failed. This parameter is passed uninitialized. ///true if value was converted successfully; otherwise, false. public static bool TryParse(object value, out T returnValue) { Type underlyingType = Enum.GetUnderlyingType(typeof(T)); bool supportedType = (value is string || value.GetType().Equals(underlyingType)); if (supportedType && Enum.IsDefined(typeof(T), value)) { //direct string or underlying type match returnValue = Parse(value.ToString()); return true; } else if (Enum.IsDefined(typeof(T), Convert.ChangeType(value, underlyingType))) // May throw overflow exception. E.g. long.MaxValue to Int32 { //underlying numeric type match after type conversion returnValue = (T)Enum.Parse(typeof(T), value.ToString()); return true; } else { //Default to the first item from the enum string[] values = Enum.GetNames(typeof(T)); returnValue = (T)Enum.Parse(typeof(T), values[0], true); //default(T) won't work for all enums. //E.g. if the underlying type for the enum is int default(T) will always return 0, for which there might not be a value. } return false; } /// <summary> /// Attempt to read the Description Attribute /// </summary> /// <param name="e">The enum value to read the description from</param> /// <returns>The description value for the enum, otherwise the enum value converted to a string.</returns> public static string EnumValueDescription(T e) { System.Reflection.FieldInfo EnumInfo = e.GetType().GetField(e.ToString()); System.ComponentModel.DescriptionAttribute[] enumAttributes = (System.ComponentModel.DescriptionAttribute[]) EnumInfo.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false); if (enumAttributes.Length > 0) { return enumAttributes[0].Description; } return e.ToString(); } /// <summary> /// Converts the string representation of the name or numeric value of one or /// more enumerated constants to an equivalent enumerated object. /// If a direct match isn't found a match will be attempted on the description attributes. /// </summary> /// <param name="value"></param> /// <param name="defaultValue"></param> /// <returns></returns> public static T ParseOrDescriptionMatch(string value, T defaultValue) { Type type = typeof(T); try { return Parse(value); } catch (Exception) { //Try Description Matching string[] names = Enum.GetNames(type); foreach (string name in names) { T nameEnum = Parse(name); string nameEnumValue = EnumValueDescription(nameEnum); if (nameEnumValue == value) { return nameEnum; } } return defaultValue; } } } }