获取 Enum 值的属性
我想知道是否可以获得 enum
值的属性而不是 enum
本身的属性?例如,假设我有以下 enum
:
using System.ComponentModel; // for DescriptionAttribute
enum FunkyAttributesEnum
{
[Description("Name With Spaces1")]
NameWithoutSpaces1,
[Description("Name With Spaces2")]
NameWithoutSpaces2
}
我想要的是给定枚举类型,生成枚举字符串值及其描述的 2 元组。
值很简单:
Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum));
foreach (int value in values)
Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value);
但是如何获取描述属性的值来填充Tuple.Desc?我可以想到如果属性属于枚举本身该怎么做,但我不知道如何从枚举的值中获取它。
I would like to know if it is possible to get attributes of the enum
values and not of the enum
itself? For example, suppose I have the following enum
:
using System.ComponentModel; // for DescriptionAttribute
enum FunkyAttributesEnum
{
[Description("Name With Spaces1")]
NameWithoutSpaces1,
[Description("Name With Spaces2")]
NameWithoutSpaces2
}
What I want is given the enum type, produce 2-tuples of enum string value and its description.
Value was easy:
Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum));
foreach (int value in values)
Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value);
But how do I get description attribute's value, to populate Tuple.Desc
? I can think of how to do it if the Attribute belongs to the enum
itself, but I am at a loss as to how to get it from the value of the enum
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(27)
我实现了这个扩展方法来从枚举值中获取描述。它适用于所有类型的枚举。
I implemented this extension method to get the description from enum values. It works for all kind of enums.
利用一些较新的 C# 语言功能,您可以减少行数:
Taking advantage of some of the newer C# language features, you can reduce the line count:
模型
我们在其中填充值的模型
枚举
我们的目标是枚举
辅助方法
我们将使用辅助方法来获取自定义属性对象
获取方法
首先,我们提取枚举值并将它们转换为枚举类型。然后,通过Linq选择查询我们知道;
我们填写它并将其变成一个列表。
Model
The model in which we fill our values
Enum
Our target is the enum
Helper Method
The helper method we will use to fetch the custom attribute object
Get Method
First we pull enum values and cast them to enum type. Then, with the Linq selection query we know;
We fill it out and turn it into a list.
现在,在这种情况下它将产生错误 1“等于”
,因此如果它相同,则返回枚举名称而不是显示名称,因为
enumMember.GetCustomAttribute()
如果显示名称和枚举名称相同,则获取 null......
Now it will produce error in this case 1 "Equals"
so if it is same return enum name rather than display name because
enumMember.GetCustomAttribute()
gets null if displayname and enum name are same.....
NuGet 包 Enums.Net 对此有很好的支持:
该包简单、直观,并完成。
它是类型安全的,并且具有缓存以避免重复反射。
GitHub 存储库 有更多信息,包括本机 Enum 的限制和功能演示:
Enums.GetMembers() 丰富迭代所有值;
The NuGet package Enums.Net has good support for this:
The package is simple, intuitive, and complete.
It's type-safe and has cache to avoid recurring reflection.
The GitHub repository has more information, including the limitations of the native Enum and a demo of functionality:
Enums.GetMembers<MyEnum>()
;此扩展方法将使用其 XmlEnumAttribute 获取枚举值的字符串表示形式。如果不存在 XmlEnumAttribute,则返回到 enum.ToString()。
This extension method will obtain a string representation of an enum value using its XmlEnumAttribute. If no XmlEnumAttribute is present, it falls back to enum.ToString().
如果你想要完整的名字列表,你可以这样做
And if you want the full list of names you can do something like
或者,您可以执行以下操作:
并获取以下描述:
在我看来,这是完成您想要完成的任务的更有效方法,因为不需要反思。
Alternatively, you could do the following:
And get the description with the following:
In my opinion this is a more efficient way of doing what you want to accomplish, as no reflection is needed..
伙计们,如果有帮助的话我会与你们分享我的解决方案:
自定义属性的定义:
现在因为我需要它在 HtmlHelper 扩展的 HtmlHelper 定义中:
希望它有帮助
Guys if it helps I will share with you my solution:
Definition of Custom attribute:
Now because I needed it inside of HtmlHelper definition of HtmlHelper Extension:
Hope it helps
或者,您可以执行以下操作:
Alternatively, you could do the following:
我创建了一个扩展方法,它将返回 C# 中枚举中所有元素的描述。
此方法将使用内置的 EnumDescription() 扩展方法添加枚举中元素的描述。
I have created an extension method that will return description of all the elements in an enum in C#.
This method will add the description of the elements in an enum using the inbuilt EnumDescription() extension method.
这就是我在不使用 .NET core 3.1 的自定义帮助程序或扩展的情况下解决该问题的方法。
类
剃须刀
This is how I solved it without using custom helpers or extensions with .NET core 3.1.
Class
Razor
这应该可以满足您的需要。
This should do what you need.
这段代码应该为您提供一个关于任何枚举的漂亮的小扩展方法,让您检索通用属性。我相信它与上面的 lambda 函数不同,因为它使用起来更简单,而且稍微 - 您只需要传入泛型类型。
那么用法将是:
This piece of code should give you a nice little extension method on any enum that lets you retrieve a generic attribute. I believe it's different to the lambda function above because it's simpler to use and slightly - you only need to pass in the generic type.
Usage would then be:
这是使用 lambda 进行选择的通用实现,
如下所示:
This is a generic implementation using a lambda for the selection
Call it like this:
我在这里合并了几个答案,以创建一个更具可扩展性的解决方案。我提供它只是为了将来对其他人有帮助。原始帖子此处。
该解决方案在 Enum 上创建了一对扩展方法。第一个允许您使用反射来检索与您的值关联的任何属性。第二个具体调用检索
DescriptionAttribute
并返回其Description
值。例如,考虑使用
System.ComponentModel
中的DescriptionAttribute
属性要使用上述扩展方法,您现在只需调用以下命令:
或
I've merged a couple of the answers here to create a little more extensible solution. I'm providing it just in case it's helpful to anyone else in the future. Original posting here.
This solution creates a pair of extension methods on Enum. The first allows you to use reflection to retrieve any attribute associated with your value. The second specifically calls retrieves the
DescriptionAttribute
and returns it'sDescription
value.As an example, consider using the
DescriptionAttribute
attribute fromSystem.ComponentModel
To use the above extension method, you would now simply call the following:
or
除了 AdamCrawford 响应 之外,我还创建了一个更专门的扩展方法,通过它来获取描述。
因此,要获取描述,您可以使用原始扩展方法,
或者您可以简单地在此处调用扩展方法:
这有望使您的代码更具可读性。
In addition to AdamCrawford response, I've further created a more specialized extension methods that feed of it to get the description.
hence, to get the description, you could either use the original extension method as
or you could simply call the the extension method here as:
Which should hopefully make your code a bit more readable.
流利的一个衬垫...
这里我使用
DisplayAttribute
,它包含Name
和Description
属性。示例
输出
Fluent one liner...
Here I'm using the
DisplayAttribute
which contains both theName
andDescription
properties.Example
Output
以下是从 Display 属性获取信息的代码。它使用通用方法来检索属性。如果找不到该属性,它会将枚举值转换为字符串,并将 pascal/camel 大小写转换为标题大小写(代码在此处获取)
这是字符串转换为标题大小写的扩展方法:
Here is code to get information from a Display attribute. It uses a generic method to retrieve the attribute. If the attribute is not found it converts the enum value to a string with pascal/camel case converted to title case (code obtained here)
And this is the extension method for strings for converting to title case:
对于一些程序员的幽默来说,一句台词就像一个笑话:
以一种更易读的形式:
For some programmer humor, a one liner as a joke:
In a more readable form:
如果您的
enum
包含像Equals
这样的值,您可能会在此处的许多答案中使用某些扩展时遇到一些错误。这是因为通常假设typeof(YourEnum).GetMember(YourEnum.Value)
只会返回一个值,即enum< 的
MemberInfo
/代码>。这是稍微安全一点的版本Adam Crawford 的回答。编辑(2023 年 5 月 3 日)
GetField
在这种情况下效果很好。typeof(YourEnum).GetField(YourEnum.Value)
应该会产生所需的结果。感谢 mjwills 指出了这一点。
If your
enum
contains a value likeEquals
you might bump into a few bugs using some extensions in a lot of answers here. This is because it is normally assumed thattypeof(YourEnum).GetMember(YourEnum.Value)
would return only one value, which is theMemberInfo
of yourenum
. Here's a slightly safer version Adam Crawford's answer.Edit (3rd May 2023)
GetField
works well in this case.typeof(YourEnum).GetField(YourEnum.Value)
should produce the desired result.Thanks to mjwills for pointing this out.
性能很重要
如果您想要更好的性能,那么可以这样:
为什么它具有更好的性能?
因为内置方法都使用与此非常相似的代码,除了它们还运行一堆我们不关心的其他代码。 C# 的 Enum 代码总体来说非常糟糕。
上面的代码已经过 Linq 化和精简,因此它只包含我们关心的位。
为什么内置代码很慢?
首先关于 Enum.ToString() -vs- Enum.GetName(..)
始终使用后者。 (或者更好的是,两者都不是,正如下面将变得清楚的那样。)
ToString() 在内部使用后者,但同样,也做了一些我们不想要的其他事情,例如尝试组合标志,打印出数字等。只对枚举内定义的常量感兴趣。
Enum.GetName依次获取所有字段,为所有名称创建一个字符串数组,在所有RawConstantValues上使用上面的ToUInt64来创建所有值的UInt64数组,根据UInt64值对两个数组进行排序,最后从通过在 UInt64 数组中执行 BinarySearch 来查找名称数组,以查找我们想要的值的索引。
...然后我们扔掉字段和排序后的数组,使用该名称再次查找字段。
一个字:“呃!”
Performance matters
If you want better performance this is the way to go:
Why does this have better performance?
Because the built-in methods all use code very similar to this except they also run a bunch of other code we don't care about. C#'s Enum code is quite horrible in general.
The above code has been Linq-ified and streamlined so it only contains the bits we care about.
Why is the built-in code slow?
First regarding Enum.ToString() -vs- Enum.GetName(..)
Always use the latter. (Or better yet neither, as will become clear below.)
ToString() uses the latter internally, but again, also does a bunch of other stuff we don't want, e.g. tries to combine flags, print out numbers etc. We are only interested in constants defined inside the enum.
Enum.GetName in turn gets all fields, creates a string array for all names, uses the above ToUInt64 on all of their RawConstantValues to create an UInt64 array of all values, sorts both arrays according to the UInt64 value, and finally gets the name from the name-array by doing a BinarySearch in the UInt64-array to find the index of the value we wanted.
...and then we throw the fields and the sorted arrays away use that name to find the field again.
One word: "Ugh!"
从枚举获取字典。
现在这样称呼它...
EnumDecription Ext 方法
Get the dictionary from enum.
Now call this like...
EnumDecription Ext Method
我这个答案是从枚举属性设置一个组合框,这非常棒。
然后我需要编写相反的代码,以便我可以从框中获取选择并以正确的类型返回枚举。
我还修改了代码来处理缺少属性的情况,
为了下一个人的利益,这是我的最终解决方案
}
I this answer to setup a combo box from an enum attributes which was great.
I then needed to code the reverse so that I can get the selection from the box and return the enum in the correct type.
I also modified the code to handle the case where an attribute was missing
For the benefits of the next person, here is my final solution
}
这是 AdamCrawford 答案的 .NET Core 版本,使用 System.Reflection.TypeExtensions;
Here's the .NET Core version of AdamCrawford's answer, using System.Reflection.TypeExtensions;
添加我的 Net Framework 和 NetCore 解决方案。
我将其用于我的 Net Framework 实现:
这不适用于 NetCore,因此我对其进行了修改以执行此操作:
枚举示例:
静态添加的示例用法:
Adding my solution for Net Framework and NetCore.
I used this for my Net Framework implementation:
This doesn't work for NetCore so I modified it to do this:
Enumeration Example:
Sample Usage for either static added:
Bryan Rowe 和 AdamCrawford 感谢您的回答!
但是如果有人需要获取描述(而不是扩展名)的方法,你可以使用它:
Bryan Rowe and AdamCrawford thanks for your answers!
But if somebody need method for get Discription (not extension) you can use it: