I am trying to create an extension method that will return a List<string> containing all the Description attributes for only the set values of a given [Flags] Enum.
For example, suppose I have the following enum declared in my C# code:
[Flags]
public enum Result
{
[Description("Value 1 with spaces")]
Value1 = 1,
[Description("Value 2 with spaces")]
Value2 = 2,
[Description("Value 3 with spaces")]
Value3 = 4,
[Description("Value 4 with spaces")]
Value4 = 8
}
And then have a variable set as:
Result y = Result.Value1 | Result.Value2 | Result.Value4;
So, the call I want to create would be:
List<string> descriptions = y.GetDescriptions();
and the final result would be:
descriptions = { "Value 1 with spaces", "Value 2 with spaces", "Value 4 with spaces" };
I have created an extension method for getting the single description attribute for an Enum that can not have multiple flags set that is along the following lines:
public static string GetDescription(this Enum value)
{
Type type = value.GetType();
string name = Enum.GetName(type, value);
if (name != null)
{
System.Reflection.FieldInfo field = type.GetField(name);
if (field != null)
{
DescriptionAttribute attr =
Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attr != null)
{
return attr.Description;
}
}
}
return null;
}
And I've found some answers online on how to get ALL the Description attributes for a given Enum type (such as here), but I'm having problems writing a generic extension method to return the list of descriptions for only the set attributes.
Any help would be really appreciated.
THANKS!!
HasFlag is your friend. :-)
The extension method below uses the GetDescription extension method you've posted above, so ensure you have that. The following should then work:
public static List<string> GetDescriptionsAsText(this Enum yourEnum)
{
List<string> descriptions = new List<string>();
foreach (Enum enumValue in Enum.GetValues(yourEnum.GetType()))
{
if (yourEnum.HasFlag(enumValue))
{
descriptions.Add(enumValue.GetDescription());
}
}
return descriptions;
}
Note: HasFlag allows you to compare a given Enum value against the flags defined. In your example, if you have
Result y = Result.Value1 | Result.Value2 | Result.Value4;
then
y.HasFlag(Result.Value1)
should be true, while
y.HasFlag(Result.Value3)
will be false.
See also: https://msdn.microsoft.com/en-us/library/system.enum.hasflag(v=vs.110).aspx
This is a compact solution using LINQ which also checks for null in case not all of the values have attributes:
public static List<T> GetFlagEnumAttributes<T>(this Enum flagEnum) where T : Attribute
{
var type = flagEnum.GetType();
return Enum.GetValues(type)
.Cast<Enum>()
.Where(flagEnum.HasFlag)
.Select(e => type.GetMember(e.ToString()).First())
.Select(info => info.GetCustomAttribute<T>())
.Where(attribute => attribute != null)
.ToList();
}
You can iterate all values from enum and then filter them that isn't contained into your input value.
public static List<T> GetAttributesByFlags<T>(this Enum arg) where T: Attribute
{
var type = arg.GetType();
var result = new List<T>();
foreach (var item in Enum.GetValues(type))
{
var value = (Enum)item;
if (arg.HasFlag(value)) // it means that '(arg & value) == value'
{
var memInfo = type.GetMember(value.ToString())[0];
result.Add((T)memInfo.GetCustomAttribute(typeof(T), false));
}
}
return result;
}
And you get list of attributes that you want:
var arg = Result.Value1 | Result.Value4;
List<DescriptionAttribute> attributes = arg.GetAttributesByFlags<DescriptionAttribute>();
Related
public enum Status
{
Pending,
[EnumMember(Value = "In Progress")]
InProgress,
Failed,
Success
}
string dbValue = "In Progress";
if (dbValue == ValueOf(Status.InProgress)){
//do some thing
}
How do I read the Value of Status.InProgress so I get back "in Progress"?
This is an extension method that works with C# 8 and nullable reference types:
public static string? GetEnumMemberValue<T>(this T value)
where T : Enum
{
return typeof(T)
.GetTypeInfo()
.DeclaredMembers
.SingleOrDefault(x => x.Name == value.ToString())
?.GetCustomAttribute<EnumMemberAttribute>(false)
?.Value;
}
Original Answer:
I've adapted this for .NET Core. Here it is:
public static String GetEnumMemberValue<T>(T value)
where T : struct, IConvertible
{
return typeof(T)
.GetTypeInfo()
.DeclaredMembers
.SingleOrDefault(x => x.Name == value.ToString())
?.GetCustomAttribute<EnumMemberAttribute>(false)
?.Value;
}
Something like this:
public string GetEnumMemberAttrValue(Type enumType, object enumVal)
{
var memInfo = enumType.GetMember(enumVal.ToString());
var attr = memInfo[0].GetCustomAttributes(false).OfType<EnumMemberAttribute>().FirstOrDefault();
if(attr != null)
{
return attr.Value;
}
return null;
}
Usage:
var enumType = typeof(Status);
var enumVal = Status.InProgress;
var str = GetEnumMemberAttrValue(enumType,enumVal);
Borrowing from Amir's answer, a slightly nicer version is possible using generics as follows:
public string GetEnumMemberAttrValue<T>(T enumVal)
{
var enumType = typeof(T);
var memInfo = enumType.GetMember(enumVal.ToString());
var attr = memInfo.FirstOrDefault()?.GetCustomAttributes(false).OfType<EnumMemberAttribute>().FirstOrDefault();
if (attr != null)
{
return attr.Value;
}
return null;
}
Usage as follows:
var enumVal = Status.InProgress;
var str = GetEnumMemberAttrValue(enumVal);
As far as I'm aware T can't be constrained to enum's using a where clause. I would be happy to be corrected though.
Wrapped it in an extension to make it feel more natural:
public static class Extension
{
public static string ToEnumMemberAttrValue(this Enum #enum)
{
var attr =
#enum.GetType().GetMember(#enum.ToString()).FirstOrDefault()?.
GetCustomAttributes(false).OfType<EnumMemberAttribute>().
FirstOrDefault();
if (attr == null)
return #enum.ToString();
return attr.Value;
}
}
Usage:
string dbValue = "In Progress";
if (dbValue == Status.ToEnumMemberAttrValue())){
//do some thing
}
If you have Newtonsoft in your project, that is what you should do:
to the Enum, you should add the attribute [JsonConverter(typeof(StringEnumConverter))]
and now you can call the JsonConvertor to serialize your value as the member string value.
in your example, it should be like that
[JsonConverter(typeof(StringEnumConverter))]
public enum Status
{
Pending,
[EnumMember(Value = "In Progress")]
InProgress,
Failed,
Success
}
string dbValue = "In Progress";
if (dbValue == JsonConvert.SerializeObject(Status.InProgress)){
//do some thing
}
Note as mentioned by #Dinesh in the comment that the string is JSON therefor return with quatos so you can workaround that to get a clean string with strin.Replace method as:
dbValue == JsonConvert.SerializeObject(Status.InProgress).Replace("\"","");
public static object GetMemberAttr(this Enum enumItem)
{
var memInfo = enumItem.GetType().GetMember(enumItem.ToString());
var attr = memInfo[0].GetCustomAttributes(false);
return attr == null || attr.Length == 0 ? null :((System.Runtime.Serialization.EnumMemberAttribute) attr[0]).Value;
}
Usage: {YouEnum}.{EnumItem}.GetMemberAttr()
public enum TEST_ENUM
{
[EnumMember(Value = "1min")]
Minute,
[EnumMember(Value = "2min")]
TwoMinutes,
[EnumMember(Value = "3min")]
ThreeMinutes,
}
public TEST_ENUM t;
? t.TwoMinutes.GetMemberAttr()
2min
Try This ,
var type = typeof(YourEnum);
var Info = type.GetMember(YourEnum.attribute); // pass enum item here
string enumdescription = Info[0].CustomAttributes.SingleOrDefault().NamedArguments[0].TypedValue.ToString();
Status.InProgress.GetStringValue()
If you have the Elasticsearch.Net library you can use this, but the other solutions here are probably better if you dont happen to already be using ES.
[EnumMember] attribute is used by a serializer such as Newtonsoft.
System.Runtime.Serialization (namespace)
EnumMemberAttribute (class)
Enum:
public enum Status
{
Pending,
[EnumMember(Value = "In Progress")]
InProgress,
Failed,
Success
}
Example code:
string databaseValue = "In Progress";
// Serialize the enum value
string statusValue = Newtonsoft.Json.JsonConvert.SerializeObject(Status.InProgress);
if (statusValue.Contains(databaseValue))
{
// Do something
}
A problem with all of the approaches post so far is that they use GetCustomAttribute<EnumMemberAttribute> for every lookup, which is somewhat expensive.
Given that attributes loaded from reflection are immutable it makes sense to cache the GetCustomAttribute<> result in-memory for each enum type (TEnum) being looked-up.
A static class<T> that's generic over T with a static initializer effectively acts as a singleton for every T, which can be used to own an ImmutableDictionary to efficiently and lazily cache the enum member attribute data:
Because the code below is generic over TEnum : struct, Enum it means there is also no boxing of enum values and it supports enums of varying underlying-type (e.g. enum Foo : int, enum Bar : long, etc):
public static class EnumMemberNames
{
public static String? GetNameOrNull<TEnum>( TEnum value ) => EnumAttribCache<TEnum>.cachedNames.TryGetValue( value, out String? text ) ? text : null;
public static String GetName<TEnum>( TEnum value ) => GetNameOrNull( value ) ?? value.ToString();
private static class EnumAttribCache<TEnum>
where TEnum : struct, Enum
{
public static readonly ImmutableDictionary<TEnum,String> cachedNames = LoadNames();
private static ImmutableDictionary<TEnum,String> LoadNames()
{
return typeof(TEnum)
.GetTypeInfo()
.DeclaredFields
.Where( f => f.IsStatic && f.IsPublic && f.FieldType == typeof(TEnum) )
.Select( f => ( field: f, attrib: f.GetCustomAttribute<EnumMemberAttribute>() ) )
.Where( t => ( t.attrib?.IsValueSetExplicitly ?? false ) && !String.IsNullOrEmpty( t.attrib.Value ) )
.ToDictionary(
keySelector : t => (TEnum)t.field.GetValue( obj: null )!,
elementSelector: t => t.attrib!.Value!
)
.ToImmutableDictionary();
}
}
}
Used like so:
enum Foo
{
[EnumMemberAttribute( Value = "first" )]
A = 1,
[EnumMemberAttribute( Value = "second" )]
B = 2,
Unnamed = 4
}
public static void Main()
{
Console.WriteLine( EnumMemberNames.GetNameOrNull( Foo.A ) ); // "first"
Console.WriteLine( EnumMemberNames.GetNameOrNull( Foo.B ) ); // "second"
Console.WriteLine( EnumMemberNames.GetName( Foo.Unnamed ) ); // "Unnamed"
}
I have the following ENUM:
[Flags]
public enum DataFiat {
[Description("Público")]
Public = 1,
[Description("Filiado")]
Listed = 2,
[Description("Cliente")]
Client = 4
} // DataFiat
And I created an extension to get an Enum attribute:
public static T GetAttribute<T>(this Enum value) where T : Attribute {
T attribute;
MemberInfo info = value.GetType().GetMember(value.ToString()).FirstOrDefault();
if (info != null) {
attribute = (T)info.GetCustomAttributes(typeof(T), false).FirstOrDefault();
return attribute;
}
return null;
}
This works for non Flags Enums ... But when I have:
var x = DataFiat.Public | DataFiat.Listed;
var y = x.GetAttribute<Description>();
The value of y is null ...
I would like to get "Público, Filiado, Cliente" ... Just as ToString() works.
How can I change my extension to make this work?
Thank You
You can use this:
var values = x.ToString()
.Split(new[] { ", " }, StringSplitOptions.None)
.Select(v => (DataFiat)Enum.Parse(typeof(DataFiat), v));
To get the individual values. Then get the attribute values of them.
Something like this:
var y2 = values.GetAttributes<DescriptionAttribute, DataFiat>();
public static T[] GetAttributes<T, T2>(this IEnumerable<T2> values) where T : Attribute
{
List<T> ts =new List<T>();
foreach (T2 value in values)
{
T attribute;
MemberInfo info = value.GetType().GetMember(value.ToString()).FirstOrDefault();
if (info != null)
{
attribute = (T)info.GetCustomAttributes(typeof(T), false).FirstOrDefault();
ts.Add(attribute);
}
}
return ts.ToArray();
}
in .NET CORE without any additional libraries you can do:
public enum Divisions
{
[Display(Name = "My Title 1")]
None,
[Display(Name = "My Title 2")]
First,
}
and to get the title:
using System.ComponentModel.DataAnnotations
using System.Reflection
string title = enumValue.GetType()?.GetMember(enumValue.ToString())?[0]?.GetCustomAttribute<DisplayAttribute>()?.Name;
I think you want to make something like that
using System;
public enum ArrivalStatus { Unknown=-3, Late=-1, OnTime=0, Early=1 };
public class Example
{
public static void Main()
{
int[] values = { -3, -1, 0, 1, 5, Int32.MaxValue };
foreach (var value in values)
{
ArrivalStatus status;
if (Enum.IsDefined(typeof(ArrivalStatus), value))
status = (ArrivalStatus) value;
else
status = ArrivalStatus.Unknown;
Console.WriteLine("Converted {0:N0} to {1}", value, status);
}
}
}
// The example displays the following output:
// Converted -3 to Unknown
// Converted -1 to Late
// Converted 0 to OnTime
// Converted 1 to Early
// Converted 5 to Unknown
// Converted 2,147,483,647 to Unknown
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
public static class Program
{
[Flags]
public enum DataFiat
{
[Description("Público")]
Public = 1,
[Description("Filiado")]
Listed = 2,
[Description("Cliente")]
Client = 4
}
public static ICollection<string> GetAttribute<T>(this Enum value)
{
var result = new Collection<string>();
var type = typeof(DataFiat);
foreach (var value1 in Enum.GetValues(type))
{
var memInfo = type.GetMember(value1.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
var description = ((DescriptionAttribute)attributes[0]).Description;
result.Add(description);
}
return result;
}
static void Main(string[] args)
{
var x = DataFiat.Public | DataFiat.Listed;
var y = x.GetAttribute<DataFiat>();
var output = string.Join(" ", y.ToArray());
Console.WriteLine(output);
}
}
I have changed the T to ICollection but you can change it as you wish or you can merege the data within the method and return the string back.
I came up with a different solution based on my previous code. It can be used as follows:
DataFiat fiat = DataFiat.Public | DataFiat.Listed;
var b = fiat.ToString();
var c = fiat.GetAttributes<TextAttribute>();
var d = fiat.GetAttributes<TextAttribute, String>(x => String.Join(",", x.Select(y => y.Value)));
I think it becomes easy to use either to get the attributes or doing something with them.
What do you think?
Let me know if the code can be somehow improved. Here is the code:
public static List<T> GetAttributes<T>(this Enum value) where T : Attribute {
List<T> attributes = new List<T>();
IEnumerable<Enum> flags = Enum.GetValues(value.GetType()).Cast<Enum>().Where(value.HasFlag);
if (flags != null) {
foreach (Enum flag in flags) {
MemberInfo info = flag.GetType().GetMember(flag.ToString()).FirstOrDefault();
if (info != null)
attributes.Add((T)info.GetCustomAttributes(typeof(T), false).FirstOrDefault());
}
return attributes;
}
return null;
} // GetAttributes
public static Expected GetAttributes<T, Expected>(this Enum value, Func<List<T>, Expected> expression) where T : Attribute {
List<T> attributes = value.GetAttributes<T>();
if (attributes == null)
return default(Expected);
return expression(attributes);
} // GetAttributes
I have dropdown, which is filled from the Enum. My Solution project consists of two parts: Domain and UI projects. And this enum is a part of domain model and so it is placed inside Domain project.
public enum ActivityStatus
{
InProgress = 0,
Completed = 1,
Freezed = 2,
NotStarted = 3,
None = 4
}
I want to localise dropdown content on UI with RESX files. I looked at some solutions, and they proposed providing custom attributes on Enum fields. But I think that localisation is out of scope of my domain model, so i want to have these attributes here. Is there a way to have a localisation on UI for me?
I also have made some enumerations localized in my projects, so, I have a class like this, to create a annotation in enums:
public class LocalizedEnumAttribute : DescriptionAttribute
{
private PropertyInfo _nameProperty;
private Type _resourceType;
public LocalizedEnumAttribute(string displayNameKey)
: base(displayNameKey)
{
}
public Type NameResourceType
{
get
{
return _resourceType;
}
set
{
_resourceType = value;
_nameProperty = _resourceType.GetProperty(this.Description, BindingFlags.Static | BindingFlags.Public);
}
}
public override string Description
{
get
{
//check if nameProperty is null and return original display name value
if (_nameProperty == null)
{
return base.Description;
}
return (string)_nameProperty.GetValue(_nameProperty.DeclaringType, null);
}
}
}
I also have a EnumHelper class to use on my projects to create dictionaries of enums values localized:
public static class EnumHelper
{
// get description data annotation using RESX files when it has
public static string GetDescription(Enum #enum)
{
if (#enum == null)
return null;
string description = #enum.ToString();
try
{
FieldInfo fi = #enum.GetType().GetField(#enum.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Any())
description = attributes[0].Description;
}
catch
{
}
return description;
}
public static IDictionary<TKey, string> GetEnumDictionary<T, TKey>()
where T : struct
{
Type t = typeof (T);
if (!t.IsEnum)
throw new InvalidOperationException("The generic type T must be an Enum type.");
var result = new Dictionary<TKey, string>();
foreach (Enum r in Enum.GetValues(t))
{
var k = Convert.ChangeType(r, typeof(TKey));
var value = (TKey)k;
result.Add(value, r.GetDescription());
}
return result;
}
}
public static class EnumExtensions
{
public static string GetDescription(this Enum #enum)
{
return EnumHelper.GetDescription(#enum);
}
}
With this class you can use on your enum:
public enum ActivityStatus
{
[LocalizedEnum("InProgress", NameResourceType = typeof(Resources.Messages))]
InProgress = 0,
[LocalizedEnum("Completed", NameResourceType = typeof(Resources.Messages))]
Completed = 1,
[LocalizedEnum("Freezed", NameResourceType = typeof(Resources.Messages))]
Freezed = 2,
[LocalizedEnum("NotStarted", NameResourceType = typeof(Resources.Messages))]
NotStarted = 3,
[LocalizedEnum("None", NameResourceType = typeof(Resources.Messages))]
None = 4
}
And to create a combo box of this, you can use on the controller of asp.net mvc, something like this:
var data = EnumHelper.GetEnumDictionary<ActivityStatus, int>();
I guees you can use HttpContext.GetGlobalResourceObject() for getting localized strings for enum names:
// here you get a list of localized strings from `SiteResources.resx` where the keys of strings present by enum names
var names = (Enum.GetNames(typeof(ActivityStatus)).Select(x => HttpContext.GetGlobalResourceObject("SiteResources", x).ToString()).ToList();
So we have our enums setup like this:
[CorrelatedNumeric(0)]
[Description("USD")]
[SequenceNumber(10)]
USD = 247
Basically, another function can provide the string "USD" to me, but not the exact enum because the source of it is Excel and we can't make our users remember the enum values ;) nor would that make much sense.
Is there a way in c# to get from "USD" to 247 from having our enums setup as they are above?
Would Enum.TryParse() or Enum.Parse() do what you need?
Currency cValue = (Currency) Enum.Parse(typeof(Currency), currencyString);
Absolutely - build a Dictionary<string, YourEnumType> by reflection. Just iterate over all the fields in the enum and find the attribute values, and build up the dictionary that way.
You can see how I've done something similar in Unconstrained Melody for the description attribute, in EnumInternals:
// In the static initializer...
ValueToDescriptionMap = new Dictionary<T, string>();
DescriptionToValueMap = new Dictionary<string, T>();
foreach (T value in Values)
{
string description = GetDescription(value);
ValueToDescriptionMap[value] = description;
if (description != null && !DescriptionToValueMap.ContainsKey(description))
{
DescriptionToValueMap[description] = value;
}
}
private static string GetDescription(T value)
{
FieldInfo field = typeof(T).GetField(value.ToString());
return field.GetCustomAttributes(typeof(DescriptionAttribute), false)
.Cast<DescriptionAttribute>()
.Select(x => x.Description)
.FirstOrDefault();
}
Just do the same thing for your own attribute type.
public static object enumValueOf(string description, Type enumType)
{
string[] names = Enum.GetNames(enumType);
foreach (string name in names)
{
if (descriptionValueOf((Enum)Enum.Parse(enumType, name)).Equals(description))
{
return Enum.Parse(enumType, name);
}
}
throw new ArgumentException("The string is not a description of the specified enum.");
}
public static string descriptionValueOf(Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[]) fi.GetCustomAttributes( typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
{
return attributes[0].Description;
}
else
{
return value.ToString();
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Finding an enum value by its Description Attribute
I have a generic extension method which gets the Description attribute from an Enum:
enum Animal
{
[Description("")]
NotSet = 0,
[Description("Giant Panda")]
GiantPanda = 1,
[Description("Lesser Spotted Anteater")]
LesserSpottedAnteater = 2
}
public static string GetDescription(this Enum value)
{
FieldInfo field = value.GetType().GetField(value.ToString());
DescriptionAttribute attribute
= Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))
as DescriptionAttribute;
return attribute == null ? value.ToString() : attribute.Description;
}
so I can do...
string myAnimal = Animal.GiantPanda.GetDescription(); // = "Giant Panda"
now, I'm trying to work out the equivalent function in the other direction, something like...
Animal a = (Animal)Enum.GetValueFromDescription("Giant Panda", typeof(Animal));
public static class EnumEx
{
public static T GetValueFromDescription<T>(string description) where T : Enum
{
foreach(var field in typeof(T).GetFields())
{
if (Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) is DescriptionAttribute attribute)
{
if (attribute.Description == description)
return (T)field.GetValue(null);
}
else
{
if (field.Name == description)
return (T)field.GetValue(null);
}
}
throw new ArgumentException("Not found.", nameof(description));
// Or return default(T);
}
}
Usage:
var panda = EnumEx.GetValueFromDescription<Animal>("Giant Panda");
rather than extension methods, just try a couple of static methods
public static class Utility
{
public static string GetDescriptionFromEnumValue(Enum value)
{
DescriptionAttribute attribute = value.GetType()
.GetField(value.ToString())
.GetCustomAttributes(typeof (DescriptionAttribute), false)
.SingleOrDefault() as DescriptionAttribute;
return attribute == null ? value.ToString() : attribute.Description;
}
public static T GetEnumValueFromDescription<T>(string description)
{
var type = typeof(T);
if (!type.IsEnum)
throw new ArgumentException();
FieldInfo[] fields = type.GetFields();
var field = fields
.SelectMany(f => f.GetCustomAttributes(
typeof(DescriptionAttribute), false), (
f, a) => new { Field = f, Att = a })
.Where(a => ((DescriptionAttribute)a.Att)
.Description == description).SingleOrDefault();
return field == null ? default(T) : (T)field.Field.GetRawConstantValue();
}
}
and use here
var result1 = Utility.GetDescriptionFromEnumValue(
Animal.GiantPanda);
var result2 = Utility.GetEnumValueFromDescription<Animal>(
"Lesser Spotted Anteater");
The solution works good except if you have a Web Service.
You would need to do the Following as the Description Attribute is not serializable.
[DataContract]
public enum ControlSelectionType
{
[EnumMember(Value = "Not Applicable")]
NotApplicable = 1,
[EnumMember(Value = "Single Select Radio Buttons")]
SingleSelectRadioButtons = 2,
[EnumMember(Value = "Completely Different Display Text")]
SingleSelectDropDownList = 3,
}
public static string GetDescriptionFromEnumValue(Enum value)
{
EnumMemberAttribute attribute = value.GetType()
.GetField(value.ToString())
.GetCustomAttributes(typeof(EnumMemberAttribute), false)
.SingleOrDefault() as EnumMemberAttribute;
return attribute == null ? value.ToString() : attribute.Value;
}
Should be pretty straightforward, its just the reverse of your previous method;
public static int GetEnumFromDescription(string description, Type enumType)
{
foreach (var field in enumType.GetFields())
{
DescriptionAttribute attribute
= Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))as DescriptionAttribute;
if(attribute == null)
continue;
if(attribute.Description == description)
{
return (int) field.GetValue(null);
}
}
return 0;
}
Usage:
Console.WriteLine((Animal)GetEnumFromDescription("Giant Panda",typeof(Animal)));
You can't extend Enum as it's a static class. You can only extend instances of a type. With this in mind, you're going to have to create a static method yourself to do this; the following should work when combined with your existing method GetDescription:
public static class EnumHelper
{
public static T GetEnumFromString<T>(string value)
{
if (Enum.IsDefined(typeof(T), value))
{
return (T)Enum.Parse(typeof(T), value, true);
}
else
{
string[] enumNames = Enum.GetNames(typeof(T));
foreach (string enumName in enumNames)
{
object e = Enum.Parse(typeof(T), enumName);
if (value == GetDescription((Enum)e))
{
return (T)e;
}
}
}
throw new ArgumentException("The value '" + value
+ "' does not match a valid enum name or description.");
}
}
And the usage of it would be something like this:
Animal giantPanda = EnumHelper.GetEnumFromString<Animal>("Giant Panda");
You need to iterate through all the enum values in Animal and return the value that matches the description you need.