如何有效地获取枚举中每个值的值和属性?
Posted
技术标签:
【中文标题】如何有效地获取枚举中每个值的值和属性?【英文标题】:How to efficiently get value and attribute for each value in an enum? 【发布时间】:2021-11-12 15:09:54 【问题描述】:我想获取enum
中每个值的值和属性。
我知道我可以循环这些值。
foreach (TEnum value in Enum.GetValues(typeof(TEnum)))
MemberInfo? info = value.GetType().GetMember(value.ToString()).FirstOrDefault();
if (info != null)
CustomAttribute? attribute = info.GetCustomAttribute<CustomAttribute>();
if (attribute != null)
EnumLookup.Add(attribute.Code, value)
但这似乎非常低效,必须为每个值调用 GetMember()
和 GetCustomAttribute()
。
如果我使用GetMembers()
或GetFields()
来获取所有枚举值的信息,然后循环遍历它们,似乎效率会更高。
FieldInfo[]? fields = typeof(TEnum).GetFields(BindingFlags.Public | BindingFlags.Static);
foreach (FieldInfo field in fields)
CustomAttribute? attribute = field.GetCustomAttribute<CustomAttribute>();
if (attribute != null)
EnumLookup.Add(code, /* Whoops! What to put here? */ );
但是我怎样才能得到每一个的价值呢?
枚举很奇怪,因为值类似于静态字段,但似乎无法通过反射获取静态字段的值。
注意:EnumLookup
是一个将代码(存储在CustomAttribute
)映射到枚举值的字典。
【问题讨论】:
您的反射代码是否存储在字典中?所以如果我理解正确的话,它只会在运行时执行一次? @Mahmoud:我不确定将反射代码存储在字典中意味着什么。我正在使用反射来 build 字典。它在一个类中,所以如果类是静态的,那么它只会初始化字典一次。问题是我有很多实例,我的一些枚举有很多值。所以我想提高效率。 抱歉模糊的注释,将自定义属性类型存储在字典中?你在字典中存储什么?还有The problem is that I have a number of instances
的实例数到底是什么?
my enums have many values
你的意思是很多枚举,很多枚举枚举值,每个都有属性??
@Mahmoud:该属性包含一个字符串值(如DescriptionAttribute
),我将该字符串值映射到枚举值(Dictionary<string, TEnum>
)。我有一个类,该类的每个实例都管理这样一个字典。我有很多该类的实例。
【参考方案1】:
我建议你有某种商店让我们称之为EnumsAttributesStore
,它在运行时只扫描你的程序集一次,并且对于每个枚举类型T
它调用它Enum.GetValues
,然后它获取自定义属性对于那个枚举成员。
之后,您公开了一种方法ResolveMemberValue<TEnum>(string memberName)
,而EnumsAttributesStore
需要做的只是查找某种哈希表IDictionary<TEnum, (Attribute customAttribute, object value)
。
因此,该代码仅在运行时通过扫描您的程序集完成一次,之后代码的使用者,他们需要做的就是调用您的 ResolveMemberValue
或任何您想要调用它来获取属性或可能来自枚举枚举值的偶数。
所以这个想法基本上是因为你的大部分工作实际上是静态的,你只能在运行时做一次。但是如果你需要比这更有效,你必须在较低的级别上处理,例如IL
。
或者更好的是,根据您的最后评论,您似乎不关心枚举的单个值,您将需要某些枚举类型的所有值并且您不关心顺序。您可以轻松地映射到字典字典中,例如 IDictionary<EnumType, IDictionary<string,string>>
。您输入枚举的类型,您会收到一个哈希映射,其中键是单个枚举名称,值是属性的值,所有这些仅在运行时的程序集加载中完成一次。
【讨论】:
事实上,我只会在第一次需要这些表时构建一次。似乎我应该能够遍历成员而不是查找每个值的成员。我需要将属性值映射到枚举,我不想将枚举映射到其他字典。【参考方案2】:所以,我发现枚举值的行为类似于静态字段。所以我可以枚举我的枚举类型的字段。要获取静态字段的值,您只需将null
传递给FieldInfo.GetValue()
。
这让我不必每次循环都调用GetMember()
。
FieldInfo[] fieldsInfo = typeof(TEnum).GetFields(BindingFlags.Public | BindingFlags.Static);
foreach (FieldInfo fieldInfo in fieldsInfo)
CustomAttribute? attribute = fieldInfo.GetCustomAttribute<CustomAttribute>();
if (attribute != null)
EnumLookup.Add(attribute.Code, (TEnum)fieldInfo.GetValue(null));
不幸的是,启用nullable
后,它会警告我该字段值可能为空,即使它不能为空。接下来会解决这个问题。
【讨论】:
以上是关于如何有效地获取枚举中每个值的值和属性?的主要内容,如果未能解决你的问题,请参考以下文章