ID #38681

枚举的显示和绑定

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

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

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

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

  Code

/// <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属性,给使用时更多选择。

  Code

static private Dictionary<string, string> _cacheEnumShowNamedDic = new Dictionary<string, string>();

/**//// <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


2009-05-29 00:00
阅读:
I'm VC , Just U know Y
本站部分文章来源于互联网,版权归原作者所有。

延伸阅读:

数组排序方法的性能比较(1):注意事项及试验

DeepEarth中的拖放行为(DragBehavior)

数组排序方法的性能比较(2):Array.Sort实现分析

wpf控件开发基础(2)

JsWebService简单应用