如何读取枚举成员属性的值
本文关键字:枚举成员 属性 读取 何读取 | 更新日期: 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 : int
、enum 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
}