How to read the Value for an EnumMember attribute
Asked Answered
H

10

43
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"?

Harrier answered 9/12, 2014 at 6:36 Comment(0)
C
41

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;
}
Confluent answered 2/10, 2017 at 3:37 Comment(1)
.SingleOrDefault(x => x.Name == value.ToString()) <-- Methinks that can be significantly optimized...Gratulate
E
27

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);
Exploratory answered 9/12, 2014 at 6:50 Comment(0)
P
17

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.

Pugnacious answered 16/11, 2016 at 3:9 Comment(1)
You can as of c# 7.3: learn.microsoft.com/en-us/dotnet/csharp/whats-new/…Oubre
F
16

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
}
Fic answered 31/8, 2018 at 20:42 Comment(0)
D
10

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("\"","");
Derogatory answered 3/2, 2021 at 11:57 Comment(3)
The JsonConvert SerializeObject returned the enum string with double quotes, do you have any solution for this issue?Loophole
@DineshPhalwadiya yes, you are right. actualy I used it with string.Replace method like so: JsonConvert.SerializeObject(whatever).Replace("\"","")Derogatory
Thanks for the response @Derogatory , I used StringEnumConverter & EnumMember to work it for meLoophole
G
5

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 )
        where TEnum : struct, Enum
    {
        return EnumAttribCache<TEnum>.cachedNames.TryGetValue( value, out String? text ) ? text : null;
    }

    public static String GetName<TEnum>( TEnum value )
        where TEnum : struct, Enum
    {
        return 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"
}
Gratulate answered 5/11, 2021 at 1:5 Comment(4)
If I use the above code I receive a compile error "The type 'TEnum' must be a non-nullable value type in order to use it as parameter 'TEnum' on GetNameOrNull method.Comeback
@Comeback What line gives you that error?Gratulate
the public static String? GetNameOrNull. If I add a where TEnum : struct, Enum then it resolves the error for me.Comeback
@Comeback Ah, thank you - I'll correct my answer now.Gratulate
M
3
    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

Microgroove answered 18/6, 2020 at 11:16 Comment(0)
S
1

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();
Sorbian answered 28/11, 2018 at 8:52 Comment(0)
D
1

[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
}
Driblet answered 10/5, 2021 at 23:47 Comment(0)
S
0

Wrote a simple extension method.

public static class EnumExtensions
{
    public static string ToEnumMememberAttributeValue(this Enum value)
    {
       var enumType = value.GetType();
       var enumMemeberAttribute = enumType
        .GetTypeInfo()
        .DeclaredMembers
        .Single(x => x.Name == value.ToString())
        .GetCustomAttribute<EnumMemberAttribute>(false);

        if (enumMemeberAttribute == null)
        {
            throw new NotSupportedException($"Enum: '{enumType.FullName}', value: {value} does not have attribute: '{nameof(EnumMemberAttribute)}'.");
        }

        return enumMemeberAttribute.Value;
    }

}

Sheasheaf answered 13/3, 2024 at 13:35 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Fair

© 2022 - 2025 — McMap. All rights reserved.