VB.NET 枚举 描述 中文 ComponentModel.Description DescriptionAttribute

前端之家收集整理的这篇文章主要介绍了VB.NET 枚举 描述 中文 ComponentModel.Description DescriptionAttribute前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

本文核心代码来自网上现有的C#代码,稍稍改了一下,所以不做原创发布。

下面例子中定义的枚举,既可以在程序内部使用枚举定义的枚举名或者枚举值,又可以向用户展示枚举的描述值,可以避免使用中文来定义枚举的尴尬以及可能会带来的未知bug。

先来几张不需要说明的图片,能看懂为啥要放这些图片就看,看不懂就怪我咯!~



代码正式开始

Imports System.ComponentModel
Imports System.Runtime.CompilerServices

Module Module1
    ''' <summary>
    ''' 指定筛选模式
    ''' </summary>
    Public Enum ReleFieldMode
        <Description("不限")>
        None
        <Description("店铺名称")>
        Title
        <Description("旺旺名称")>
        WangWang
    End Enum

    Sub Main()
        For Each enumItem As ReleFieldMode In System.Enum.GetValues(GetType(ReleFieldMode))
            Console.WriteLine("枚举名:" & enumItem.ToString() & " 枚举值:" & enumItem & " 描述:" & enumItem.GetDescription)
        Next

        Console.ReadKey()
    End Sub

    ''' <summary>
    ''' 利用反射获取枚举项的描述
    ''' </summary>
    ''' <param name="enumItem"></param>
    ''' <returns></returns>
    <Extension()>
    Public Function GetDescription(ByVal enumItem As System.Enum) As String
        If enumItem Is Nothing Then Return String.Empty
        ' #########扩展方法必须要放到模块(Module)中#########
        ' 利用反射获取枚举项的描述
        Dim enumItemName = enumItem.ToString()
        Dim enumItemType = enumItem.GetType()
        Dim fieldinfo = enumItemType.GetField(enumItemName)
        Dim obj = fieldinfo.GetCustomAttributes(GetType(DescriptionAttribute),False)

        If obj.Length = 0 Then
            Return String.Empty
        Else
            Dim desc = DirectCast(obj.First,DescriptionAttribute)
            Return desc.Description
        End If
    End Function

End Module

效果

另外放一些跟反射相关的图片

测试环境:VS2017 & Win7 64 & .NET Framework4.5.2

20170429更新
修复无法正确获取到多态枚举项的描述的问题
另外,增加一个判断条件,条件为:
枚举必须按照建议定义None和All项,否则一律返回空值

''' <summary>
        ''' 通过反射得到单个枚举项的描述
        ''' 如果获取多个枚举项的描述,需要用Multiple版本,否则无法正确获取
        ''' </summary>
        ''' <param name="enumItem"></param>
        ''' <returns></returns> 
        <Extension()>
        Public Function GetDescriptionSingle(ByVal enumItem As System.Enum) As String
            Dim funcResult = String.Empty

            Dim enumItemType = enumItem.GetType()
            Dim enumItemName = enumItem.ToString()
            Dim fieldinfo = enumItemType.GetField(enumItemName)
            ' 如果enumItemName是多态枚举值或者是未找到符合指定要求的字段的对象,将返回nothing
            If fieldinfo Is Nothing Then
                Return funcResult
            End If

            Dim obj = fieldinfo.GetCustomAttributes(GetType(System.ComponentModel.DescriptionAttribute),False)

            If obj.Length = 0 Then
                Return funcResult
            Else
                Dim descriptionAttribute = DirectCast(obj.First,System.ComponentModel.DescriptionAttribute)
                If descriptionAttribute Is Nothing Then
                    Return funcResult
                End If

                funcResult = descriptionAttribute.Description
            End If

            Return funcResult
        End Function

        ''' <summary>
        ''' 利用反射获取多个枚举项的描述
        ''' 如果获取单个枚举项的描述,用Single版本会更高效
        ''' 如果枚举类没有按照建议的格式来定义,则返回空值
        ''' 建议None定义为0,与All同时被定义到枚举项中
        ''' </summary>
        ''' <param name="enumItems">如果为Nothing,则返回空值</param>
        ''' <returns></returns>
        <Extension()>
        Public Function GetDescriptionMultiple(ByVal enumItems As System.Enum) As String
            If enumItems Is Nothing Then Return String.Empty

            ' 如果枚举类没有按照建议的格式来定义,则返回空值
            ' 建议None定义为0,与All同时被定义到枚举项中
            If Not System.Enum.IsDefined(enumItems.GetType,"None") OrElse
                       Not System.Enum.IsDefined(enumItems.GetType,"All") Then
                Return String.Empty
            End If

            ' 利用反射获取枚举项的描述
            ' 先把enumItems中包含的所有枚举项提取出来到数组中
            ' 如果有更高效的集合类,可以替换数组,因为用数组要不断ReDim Preserve
            Dim enumValues = System.Enum.GetValues(enumItems.GetType())
            Dim tempEnumItems As System.Enum() = {}
            Dim itemIndex = 0
            For Each item As System.Enum In enumValues
                If enumItems.HasFlag(item) Then
                    ReDim Preserve tempEnumItems(itemIndex)
                    tempEnumItems(itemIndex) = item
                    itemIndex += 1
                End If
            Next

            ' 然后判断数组的长度,如果大于1,那就是enumItems中不包含枚举值None项和All项(通常None定义为0,一般会与All同时被定义到枚举项中)
            Dim sb As StringBuilder = StringBuilderCache.Acquire(100)
            Dim splitString = ","
            If tempEnumItems.Length > 1 Then
                For Each enumItem In tempEnumItems
                    If enumItem.Equals(System.Enum.Parse(enumItems.GetType,"None",True)) OrElse
    enumItem.Equals(System.Enum.Parse(enumItems.GetType,"All",True)) Then
                        Continue For
                    End If

                    sb.Append(String.Concat(enumItem.GetDescriptionSingle(),splitString))
                Next
            Else
                sb.Append(String.Concat(tempEnumItems(0).GetDescriptionSingle(),splitString))
            End If

            ' 去掉最后的"," 从后面往前面判断
            If sb.Length > 0 AndAlso
                sb.Chars(sb.Length - 2).Equals(splitString.Chars(0)) AndAlso
                sb.Chars(sb.Length - 1).Equals(splitString.Chars(1)) Then
                sb.Remove(sb.Length - splitString.Length,splitString.Length)
            End If

            Return StringBuilderCache.GetStringAndRelease(sb)
        End Function

噢,上面用到的StringBuilderCache类,你们改成StringBuilder类相应的方法就可以了。

测试枚举定义(含有Flags标识,可以对枚举项进行位运算)

测试结果

猜你在找的VB相关文章