public enum Status
{
Pending,
[EnumMember(Value = "In Progress")]
InProgress,
Failed,
Success
}
string dbValue = "In Progress";
if (dbValue == ValueOf(Status.InProgress)){
//do some thing
}
如何读取 Status.InProgress 的值以便返回“进行中”?
这是一个适用于 C# 8 和可为空引用类型的扩展方法:
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);
借用阿米尔的答案,可以使用泛型得到一个稍微好一点的版本,如下所示:
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);
据我所知,不能使用 where 子句将 T 限制为枚举。不过,我很乐意得到纠正。
将其包裹在扩展中,使其感觉更自然:
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,那么您应该这样做:
对于 Enum,您应该添加属性 [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.Replace 方法获取干净的字符串:
dbValue == JsonConvert.SerializeObject(Status.InProgress).Replace("\"","");
到目前为止发布的所有方法的一个问题是,它们每次查找都使用
GetCustomAttribute<EnumMemberAttribute>
,这有点昂贵。
鉴于从反射加载的属性是不可变的,对于正在查找的每个枚举类型 (
GetCustomAttribute<>
),将 TEnum
结果缓存在内存中是有意义的。
A
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 )
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();
}
}
}
像这样使用:
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"
}
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}.{EnumItem}.GetMemberAttr() 公共枚举 TEST_ENUM { [EnumMember(值=“1分钟”)] 分钟, [EnumMember(值 = "2min")] 2分钟, [EnumMember(值 = "3min")] 三分钟, }
公共 TEST_ENUM t;
? t.TwoMinutes.GetMemberAttr()
2分钟
试试这个,
var type = typeof(YourEnum);
var Info = type.GetMember(YourEnum.attribute); // pass enum item here
string enumdescription = Info[0].CustomAttributes.SingleOrDefault().NamedArguments[0].TypedValue.ToString();
[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
}
编写了一个简单的扩展方法。
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;
}
}