如何读取枚举成员属性的值

本文关键字:枚举成员 属性 读取 何读取 | 更新日期: 2023-09-27 18:33:48

public enum Status
    {
        Pending,
        [EnumMember(Value = "In Progress")]
        InProgress,
        Failed,
        Success
    }
string dbValue = "In Progress";
if (dbValue == ValueOf(Status.InProgress)){
//do some thing
}

如何读取 Status.Infor 的值,以便返回"进行中"?

如何读取枚举成员属性的值

这是一个适用于 C# 8 和可为 null 的引用类型的扩展方法:

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;
}

原答案:

我已经针对.NET Core进行了改编。在这里:

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;
}

像这样:

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;
}

用法:

var enumType = typeof(Status);
var enumVal = Status.InProgress;
var str = GetEnumMemberAttrValue(enumType,enumVal);

借用 Amir 的回答,使用泛型可以稍微好一点的版本,如下所示:

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;
}

用法如下:

var enumVal = Status.InProgress;
var str = GetEnumMemberAttrValue(enumVal);

据我所知,不能将 T 限制为使用 where 子句的枚举。不过,我很乐意得到纠正。

将其包装在扩展中以使其感觉更自然:

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;
    }
}

用法:

string dbValue = "In Progress";
if (dbValue == Status.ToEnumMemberAttrValue())){
    //do some thing
}

如果你的项目中有Newtonsoft,那就是你应该做的:

到枚举中,您应该添加属性 [JsonConverter(typeof(StringEnumConverter))]

现在,您可以调用 JsonConvertor 将值序列化为成员字符串值。

在你的例子中,它应该是这样的

[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
}

请注意,正如@Dinesh在注释中提到的,该字符串是 JSON,因此返回带有 quatos 的字符串,因此您可以解决此问题以获得带有 strin 的干净字符串。将方法替换为:

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;
    }

用法:{YouEnum}。{枚举项}.GetMemberAttr() 公共枚举TEST_ENUM { [枚举成员(值 = "1分钟")] 分钟 [枚举成员(值 = "2分钟")] 两分钟, [枚举成员(值 = "3分钟")] 三分钟, }

公共TEST_ENUM t;

? t.TwoMinutes.GetMemberAttr()
2分钟

到目前为止,

所有方法的一个问题是它们每次查找都使用GetCustomAttribute<EnumMemberAttribute>,这有点昂贵。

鉴于从反射加载的属性是不可变的,因此将GetCustomAttribute<>结果缓存在内存中对于正在查找的每个枚举类型(TEnum)是有意义的。

一个具有静态初始值设定项的泛型static class<T>T上是泛型的,有效地充当每个T单例,可用于拥有高效和懒惰地缓存枚举成员属性数据的ImmutableDictionary

因为下面的代码是通用的TEnum : struct, Enum这意味着枚举值也没有装箱,它支持不同底层类型的枚举(例如 enum Foo : intenum Bar : long等):

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();
        }
    }
}

像这样使用:

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"
}

试试这个,

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()

如果你有 Elasticsearch.Net 库,你可以使用它,但如果你没有碰巧已经在使用 ES,这里的其他解决方案可能会更好。

[EnumMember]属性由 Newtonsoft 等序列化程序使用。

System.Runtime.Serialization(命名空间)

EnumMemberAttribute(类)

枚举:

public enum Status
{
    Pending,
    [EnumMember(Value = "In Progress")]
    InProgress,
    Failed,
    Success
}

示例代码:

string databaseValue = "In Progress";
// Serialize the enum value
string statusValue = Newtonsoft.Json.JsonConvert.SerializeObject(Status.InProgress);
if  (statusValue.Contains(databaseValue))
{
    // Do something
}