zoukankan      html  css  js  c++  java
  • [转]用反射+特性列出所有的枚举变量及其描述信息,绑定到DropDownList上。

    1。问题

        在设计实体类的时候,通常我们会把某些字段设置为枚举值,例如性别:

    public enum Sex:int
    {
        Male 
    = 'M',Female = 'W',NotRestrict = 'A'
    }
        
        这样好处不用说,通常是为了直观的考虑,还有限制输入的好处;如果强制用int转换,还以用System.Enum.IsDefined() 来判断枚举是否被定义,但是麻烦的是在界面UI上绑定的时候,我们通常要这样写:

        <asp:DropDownList Runat="server" id="ddlSex">
            
    <asp:ListItem Value="M"></asp:ListItem>
            
    <asp:ListItem Value="W"></asp:ListItem>
            
    <asp:ListItem Value="A">不限</asp:ListItem>
        
    </asp:DropDownList>
        
        然后如果要取得枚举的值,则:

        Sex sex = (Sex)ddlSex.SelectedValue.ToCharArray()[0];

        取值的时候其实没有多大问题,问题在UI上面

    1. 首先要知道所有枚举的值:例如'W','M','A'等
    2. 需要知道枚举值的名称,通常使用中文,例如'男','女'等,界面设计人员无法确定使用什么中文描述。
    3. 枚举的项目改变的时候,所有的绑定都需要改变。

    2。解决了吗?

        解决描述的问题很简单,使用XML文档就可以了。
        只要在项目输出的时候输出XML文档,并且文档的名字跟DLL的名字一致就可以了。

        需要丰富枚举定义:

        /// <summary>
        
    /// 性别
        
    /// </summary>

        public enum Sex:int
        
    {    
            
    /// <summary>
            
    /// 男
            
    /// </summary>

            Male 
    = 'M',
            
    /// <summary>
            
    /// 女
            
    /// </summary>

            Female 
    = 'W',
            
    /// <summary>
            
    /// 不限
            
    /// </summary>

            NotRestrict 
    = 'A'
        }

        这样虽然2的问题解决了,1、3还是没有解决。    
        解决的办法是,使用  

        System.Enum.GetValues(typeof(sex));
       
        来获得所有的枚举值,然后用foreach调用:

        ddlSex.Items.Clear();
        
    foreach(Sex sex1 in System.Enum.GetValues(typeof(Sex)))
        
    {
            ListItem item 
    = new ListItem(sex1.ToString(),((char)sex1).ToString());
            ddlSex.Items.Add(item);
        }

        这样1,3的问题就解决了!美中不足的是列表项显示的是英文,如果想要解决也未尝不可:

    1. 把枚举的项改成中文的(-_-!,这个也太.......)
    2. 使用 反射+特性(Attribute)解决!

    3。最终解决办法!

        首先,给枚举值加上特性描述

        public enum Sex:int
        
    {
            [Description(
    "")]
            Male 
    = 'M',
            [Description(
    "")]
            Female 
    = 'W',
            [Description(
    "不限")]
            NotRestrict 
    = 'A'
        }

        然后使用反射来读这个值:



        
    /// <summary>
        
    /// 获得某个Enum类型的绑定列表
        
    /// </summary>
        
    /// <param name="enumType">枚举的类型,例如:typeof(Sex)</param>
        
    /// <returns>
        
    /// 返回一个DataTable
        
    /// DataTable 有两列:    "Text"    : System.String;
        
    ///                        "Value"    : System.Char
        
    /// </returns>

        public static DataTable EnumListTable(Type enumType)
        
    {
            
    if(enumType.IsEnum != true)
            
    {    //不是枚举的要报错
                throw new InvalidOperationException();
            }


            
    //建立DataTable的列信息
            DataTable dt = new DataTable();
            dt.Columns.Add(
    "Text",typeof(System.String));
            dt.Columns.Add(
    "Value",typeof(System.Char));
                        
            
    //获得特性Description的类型信息
            Type typeDescription = typeof(DescriptionAttribute);

            
    //获得枚举的字段信息(因为枚举的值实际上是一个static的字段的值)
            System.Reflection.FieldInfo[] fields = enumType.GetFields();
            
            //检索所有字段
            foreach(FieldInfo field in fields)
            
    {
                
    //过滤掉一个不是枚举值的,记录的是枚举的源类型
                if(field.FieldType.IsEnum == true)
                
    {
                    DataRow dr 
    = dt.NewRow();

                    
    // 通过字段的名字得到枚举的值
                    
    // 枚举的值如果是long的话,ToChar会有问题,但这个不在本文的讨论范围之内
                    dr["Value"= (char)(int)enumType.InvokeMember(field.Name,BindingFlags.GetField,null,null,null);

                    
    //获得这个字段的所有自定义特性,这里只查找Description特性
                    object[] arr = field.GetCustomAttributes(typeDescription,true);
                    
    if(arr.Length > 0)
                    
    {
                        
    //因为Description这个自定义特性是不允许重复的,所以我们只取第一个就可以了!
                        DescriptionAttribute aa = (DescriptionAttribute)arr[0];
                        
    //获得特性的描述值,也就是‘男’‘女’等中文描述
                        dr["Text"= aa.Description;
                    }

                    
    else
                    
    {
                        
    //如果没有特性描述(-_-!忘记写了吧~)那么就显示英文的字段名
                        dr["Text"= field.Name;
                    }

                    dt.Rows.Add(dr);
                }

            }

            
            
    return dt;
        }

        
        使用方法如下:

        DataTable dt = EnumListTable(typeof(Sex));
        ddlSex.DataSource 
    = dt;
        ddlSex.DataTextField 
    = "Text";
        ddlSex.DataValueField 
    = "Value";

       
        怎么样?方便吧?而且这个是通用的函数,适合于所有Enum,
        前提条件是枚举值的所占的空间大小最好不要超过int。还有就是记得写描述的值,呵呵。

    来自:http://www.cnblogs.com/yzxchoice/archive/2006/09/29/518122.html
       

  • 相关阅读:
    解决electron-vue中无法使用Element的Tooltip组件
    解决Electron安装包下载慢的问题
    虚拟机VirtualBox 共享挂载问题:mount: /mnt/xxx: wrong fs type, bad option, bad superblock on xxx
    git 设置和取消代理
    (转载)数据库连接池到底应该设多大?这篇文章可能会颠覆你的认知
    MySQL主主复制+MMM实现高可用
    Mysql5.6主从热备配置
    java 启动 shell脚本
    redis批量删除key
    spring mvc异常统一处理(ControllerAdvice注解)
  • 原文地址:https://www.cnblogs.com/xbf321/p/1033899.html
Copyright © 2011-2022 走看看