Я являюсь поклонником VB.NET, поэтому вот моя версия, сочетающая метод DescriptionAttribute с методом расширения. Во-первых, результаты:
Imports System.ComponentModel ' For <Description>
Module Module1
''' <summary>
''' An Enum type with three values and descriptions
''' </summary>
Public Enum EnumType
<Description("One")>
V1 = 1
' This one has no description
V2 = 2
<Description("Three")>
V3 = 3
End Enum
Sub Main()
' Description method is an extension in EnumExtensions
For Each v As EnumType In [Enum].GetValues(GetType(EnumType))
Console.WriteLine("Enum {0} has value {1} and description {2}",
v,
CInt(v),
v.Description
)
Next
' Output:
' Enum V1 has value 1 and description One
' Enum V2 has value 2 and description V2
' Enum V3 has value 3 and description Three
End Sub
End Module
Базовый материал: enumType с тремя значениями V1, V2 и V3. «Волшебство» происходит в вызове Console.WriteLine в Sub Main (), где последний аргумент просто v.Description
. Это возвращает «Один» для V1, «V2» для V2 и «Три» для V3. Этот Description-метод на самом деле является методом расширения, определенным в другом модуле с именем EnumExtensions:
Option Strict On
Option Explicit On
Option Infer Off
Imports System.Runtime.CompilerServices
Imports System.Reflection
Imports System.ComponentModel
Module EnumExtensions
Private _Descriptions As New Dictionary(Of String, String)
''' <summary>
''' This extension method adds a Description method
''' to all enum members. The result of the method is the
''' value of the Description attribute if present, else
''' the normal ToString() representation of the enum value.
''' </summary>
<Extension>
Public Function Description(e As [Enum]) As String
' Get the type of the enum
Dim enumType As Type = e.GetType()
' Get the name of the enum value
Dim name As String = e.ToString()
' Construct a full name for this enum value
Dim fullName As String = enumType.FullName + "." + name
' See if we have looked it up earlier
Dim enumDescription As String = Nothing
If _Descriptions.TryGetValue(fullName, enumDescription) Then
' Yes we have - return previous value
Return enumDescription
End If
' Find the value of the Description attribute on this enum value
Dim members As MemberInfo() = enumType.GetMember(name)
If members IsNot Nothing AndAlso members.Length > 0 Then
Dim descriptions() As Object = members(0).GetCustomAttributes(GetType(DescriptionAttribute), False)
If descriptions IsNot Nothing AndAlso descriptions.Length > 0 Then
' Set name to description found
name = DirectCast(descriptions(0), DescriptionAttribute).Description
End If
End If
' Save the name in the dictionary:
_Descriptions.Add(fullName, name)
' Return the name
Return name
End Function
End Module
Поскольку поиск атрибутов описания с использованием Reflection
выполняется медленно, поиск также кэшируется в приватном Dictionary
, который заполняется по требованию.
(Извините за решение VB.NET - переводить его на C # должно быть относительно просто, а мой C # ржавеет по новым темам, таким как расширения)