吴义法

导航

枚举的显示和绑定

1.定义一个存储枚举的显示名称的定制特性:


/// <summary>
/// 枚举的显示名称
/// </summary>
[global::System.AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
public sealed class EnumShowNameAttribute : Attribute
{
    
/// <summary>
    
/// 显示名称
    
/// </summary>
    public string ShowName { getprivate set; }

 

 

/// <summary>
    
/// 构造枚举的显示名称
    
/// </summary>
    
/// <param name="showName">显示名称</param>
    public EnumShowNameAttribute(string showName)
    {
        
this.ShowName = showName;
    }
}

 

2.为每个枚举的成员添加此定制特性。如:


/// <summary>
/// 性别
/// </summary>
public enum Sex
{
    
/// <summary>
    
/// 男
    
/// </summary>
    [EnumShowName("")]
    Man
=0,
    
/// <summary>
    
/// 女
    
/// </summary>
    [EnumShowName("")]
    Woman
=1,
}

 

3.写显示枚举名称、绑定控件的扩展方法。
显示枚举名称方法(ToShowName())的思路本来很简单:根据枚举值获取其EnumShowNameAttribute定制特性的ShowName属性值。但我这里的代码并不少,主要用来处理以下几点:
1.缓存。由于用反射的方式获取值性能不好。于是这里用了一个Dictionary<string,string>来缓存枚举值对应的ShowName,Key是[枚举类的FullName].[枚举值的ToString],Value是ShowName值。那么只是第一次访问的时候需要反射,以后都从缓存里取就行了。
2.FlagsAttribute标记的枚举。此标志表示这个枚举按位排列。那么不缓存它,且需要拿输入值与枚举的成员一个一个比较。
另:绑定的时候应尊重控件的AppendDataBoundItems属性,给使用时更多选择。


static private Dictionary<stringstring> _cacheEnumShowNamedDic = new Dictionary<stringstring>();

/// <summary>
        
/// 输出枚举的ShowName,需要枚举声明EnumShowNameAttribute
        
/// </summary>
        
/// <param name="en">待输出的枚举</param>
        
/// <returns></returns> 

static public string ToShowName(this Enum en)
        
{
            
return ToShowName(en, false",");
        }


/// <summary>
        
/// 输出枚举的ShowName,需要枚举声明EnumShowNameAttribute
        
/// </summary>
        
/// <param name="en">待输出的枚举</param>
        
/// <param name="exceptionIfNotSuccess">未成功是否抛出异常</param>
        
/// <param name="flagsSeparator">Flags类型输出时的间隔符</param>
        
/// <returns></returns> 

static public string ToShowName(this Enum en, bool exceptionIfFail,string flagsSeparator)
        
{
            
string showName;
            
string enFullName = GetEnumFullName(en);

            
// 先在缓存中找
            if (!_cacheEnumShowNamedDic.TryGetValue(enFullName, out showName))
            
{
                
// 获取枚举类型
                Type enumType = en.GetType();

                
// 查看其是否Flags
                object[] flagsAtts = enumType.GetCustomAttributes(typeof(FlagsAttribute), false);

                
// 有Flags,按位处理,不缓存
                if (flagsAtts != null && flagsAtts.Length > 0)
                
{
                    
long currentVal = Convert.ToInt64(en);
                    StringBuilder sb 
= new StringBuilder();

                    
string[] names = Enum.GetNames(enumType);
                    
string zeroString = "";

                    
foreach (string name in names)
                    
{
                        
long val = Convert.ToInt64(Enum.Parse(enumType, name));

                        
// val为0,则跳过
                        if (val == 0)
                        
{
                            
object[] atts = enumType.GetField(name).GetCustomAttributes(typeof(EnumShowNameAttribute), false);
                            
if (atts.Length > 0)
                            
{
                                
// 找到,设置
                                zeroString = ((EnumShowNameAttribute)atts[0]).ShowName;
                            }

                            
continue;
                        }


                        
// 比较
                        if ((val & currentVal) == val)
                        
{
                            
// 加间隔符
                            if (sb.Length != 0)
                            
{
                                sb.Append(flagsSeparator);
                            }


                            
// 加上定制特性值
                            object[] atts = enumType.GetField(name).GetCustomAttributes(typeof(EnumShowNameAttribute), false);
                            
if (atts.Length > 0)
                            
{
                                
// 找到,设置
                                sb.Append(((EnumShowNameAttribute)atts[0]).ShowName);
                            }

                            
else
                            
{
                                
// 没找到定制特性,参数指定抛出异常则抛出异常
                                if (exceptionIfFail)
                                
{
                                    
throw new InvalidOperationException(string.Format("此枚举{0}未定义EnumShowNameAttribute", enFullName));
                                }


                                sb.Append(name);
                            }

                        }

                    }


                    
// 输出
                    if (sb.Length > 0)
                    
{
                        
return sb.ToString();
                    }

                    
return zeroString;
                }

                
// 无Flags
                else
                
{
                    
// 找字段
                    FieldInfo fieldInfo = enumType.GetField(en.ToString());
                    
if (fieldInfo == null)
                    
{
                        
throw new InvalidOperationException(string.Format("非完整枚举{0}", enFullName));
                    }


                    
// 找定制特性
                    object[] atts = fieldInfo.GetCustomAttributes(typeof(EnumShowNameAttribute), false);
                    
if (atts.Length > 0)
                    
{
                        
// 找到,设置
                        showName = ((EnumShowNameAttribute)atts[0]).ShowName;
                        
lock (_cacheEnumShowNamedDic)
                        
{
                            _cacheEnumShowNamedDic[enFullName] 
= showName;
                        }

                    }

                    
else
                    
{
                        
// 没找到定制特性,参数指定抛出异常则抛出异常
                        if (exceptionIfFail)
                        
{
                            
throw new InvalidOperationException(string.Format("此枚举{0}未定义EnumShowNameAttribute", enFullName));
                        }


                        
// 否则直接输出本身的ToString
                        return en.ToString();
                    }

                }

            }


            
return showName;
        }


/// <summary>
/// 获取枚举的全名
/// </summary>
/// <param name="en"></param>
/// <returns></returns>

static private string GetEnumFullName(Enum en)
        
{
            
return en.GetType().FullName + "." + en.ToString();
        }


/// <summary>
/// 给ListControl绑定枚举值
/// </summary>
/// <typeparam name="T">枚举类型</typeparam>
/// <param name="listControl">待绑定的控件</param>

static public void BindEnum<T>(this System.Web.UI.WebControls.ListControl listControl)
    
where T : struct
        
{
            
// 获取类型
            Type type = typeof(T);
            
if (!type.IsEnum)
            
{
                
throw new InvalidOperationException("类型必须是枚举:" + type.FullName);
            }


            
// 获取枚举成员
            Array values = Enum.GetValues(type);

            
// 绑定值
            if (!listControl.AppendDataBoundItems)
            
{
                listControl.Items.Clear();
            }

            
foreach (Enum item in values)
            
{
                listControl.Items.Add(
new System.Web.UI.WebControls.ListItem(item.ToShowName(), item.ToString()));
            }

        }

 

4.使用。直接在枚举上ToShowName就可以得到显示的名称,在ListControl(DropDownList继承此类)用BindEnum方法绑定枚举。如:

this.ddlTest.BindEnum<Sex>();
string str = Sex.Man.ToShowName();

 

注:有多语言需求的项目和大项目,不推荐使用这种方案,而建议将显示的文字存储在单独的文件中。

参阅:http://www.cnblogs.com/zhucai/archive/2009/05/27/enum_bind.html

        http://www.cnblogs.com/JeffreyZhao/archive/2009/01/07/AttachDataExtensions.html



posted on 2010-07-16 21:33  吴义法  阅读(499)  评论(0编辑  收藏  举报