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

14 篇文章 2 订阅
14 篇文章 0 订阅

本文核心代码来自网上现有的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标识,可以对枚举项进行位运算)
这里写图片描述

测试结果
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闪星2

Time is money

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值