• 枚举的多语言显示


    关于枚举类型的多语言显示,其实就是Globalization的问题。解决方案当然不止一种,这里介绍一种可用性和扩展性的比较好的通用方法。

    显然这里自己去实现自定义格式化,即通过IFormatable、IFormatProvider、ICustomFormatter等接口已达到Globalization有点小题大作了,而另外一个很容易想到的点是通过DiaplayMember实现显示值得自定义(对于简单Binding,例如ComboBox、ListBox等只用重载ToString就可以了)。

    首先,我们希望Binding整个枚举类型的每一个值,也就是说,我们需要把这个枚举的所有值变成一个数据源,为了实现这一点,我们可以使用Enum上的helper方法Enum.GetValues(Type)来返回一个对所有值得枚举,然后依次添加到IList对象或者IListSource接口即可。

    if (!typeof(EnumType).IsEnum)
    {
        throw new NotSupportedException("Can not support type: " + typeof(EnumType).FullName);
        // It's better use resource version as below.
        // throw new NotSupportedException(SR.GetString("TYPE_NOT_SUPPORT",  typeof(EnumType).FullName));
    }
    
    // Use Enum helper enumerator list all enum values and add to current context.
    foreach (EnumType value in Enum.GetValues(typeof(EnumType)))
    {
        //TODO: add each value to IList
        base.Add(new EnumAdapter(value));
    }

    然后,取到了值,由于我们希望自定义Binding显示,那么需要对枚举值进行封装,而在这个封装里面,我们可以实现多语言的支持。

    /// <summary>
    ///   Enum value adapter, used to get values from each Cultures.
    /// </summary>
    public sealed class EnumAdapter
    {
        /**//// <summary>
        ///   Storage the actual Enum value.
        /// </summary>
        private EnumType _value;
    
        /**//// <summary>
        ///   Constructor an <see cref="EnumAdapter"/>.
        /// </summary>
        /// <param name="value">The enum value.</param>
        /// <exception cref="">
        ///   
        /// </exception>
        public EnumAdapter(EnumType value)
        {
            if (!Enum.IsDefined(typeof(EnumType), value))
            {
                throw new ArgumentException(string.Format("{0} is not defined in {1}", value, typeof(EnumType).Name), "value");
                // It's better use resource version as below.
                // throw new ArgumentException(SR.GetString("ENUM_NOT_DEFINED_FMT_KEY", value, typeof(EnumType).Name), "value");
            }
            _value = value;
        }
    
        /**//// <summary>
        ///   Gets the actual enum value.
        /// </summary>
        public EnumType Value
        {
            get { return _value; }
        }
    
        /**//// <summary>
        ///   Gets the display value for enum value by search local resource with currrent UI lture 
        ///   and special key which is concated from Enum type name and Enum value name.
        /// </summary>
        /// <remarks>
        ///   This would get correct display value by accessing location resource with current UI Culture.
        /// </remarks>
        public string DisplayValue
        {
            get { return SR.GetString(string.Format("{0}.{1}", typeof(EnumType).Name, _value.ToString())); }
        }
    
        //TODO: If you want more, please add below
    }

    至此,整个功能的框架已经完成,下面我们来看看一些细节——如何对资源读取和管理的封装:

    /// <summary>
    ///   Constructor a new <see cref="SR"/>.
    /// </summary>
    internal SR()
    {
        //TODO: If you modified resource location, please update here
        this.resources = new System.Resources.ResourceManager(
            string.Concat(typeof(EnumAdapter).Namespace, ".Resource"), 
            base.GetType().Assembly);
    }
    
    /**//// <summary>
    ///   Get singleton instance.
    /// </summary>
    /// <returns>A singleton <see cref="SR"/></returns>
    private static SR GetLoader()
    {
        if (loader == null)
        {
            lock (SR.InternalSyncObject)
            {
                if (loader == null)
                {
                    loader = new SR();
                }
            }
        }
        return loader;
    }
    
    /**//// <summary>
    ///   Gets an object from resources by special key, which provided by <paramref name="name"/>.
    /// </summary>
    /// <param name="name">Resource accessed key</param>
    /// <returns>return stored object in resource. if resource not found, return <paramref name="name"/> as object.</returns>
    public static object GetObject(string name)
    {
        SR loader = GetLoader();
        if (loader == null)
        {
            return null;
        }
        try
        {
            return loader.resources.GetObject(name, Culture);
        }
        catch { }
        return name;
    }
    
    /**//// <summary>
    ///   Gets a string from resources by special key, which provided by <paramref name="name"/>.
    /// </summary>
    /// <param name="name">Resource accessed key</param>
    /// <returns>return stored string in resource. If resource not found, retuen <paramref name="name"/> as result.</returns>
    public static string GetString(string name)
    {
        SR loader = GetLoader();
        if (loader == null)
        {
            return null;
        }
        try
        {
            return loader.resources.GetString(name, Culture);
        }
        catch { }
        return name;
    }
    
    /**//// <summary>
    ///   Gets a formatted string from resources by special key, which provided by <paramref name="name"/> and optional parameters.
    /// </summary>
    /// <param name="name">Resource accessed key</param>
    /// <param name="args">format arguments.</param>
    /// <returns>return stored string in resource. If resource not found, use <paramref name="name"/> as formator, return the formatted string.</retur
    public static string GetString(string name, params object[] args)
    {
        SR loader = GetLoader();
        if (loader == null)
        {
            return null;
        }
        string format = name;
        try
        {
            format = loader.resources.GetString(name, Culture);
        }
        catch { }
    
        if ((args == null) || (args.Length <= 0))
        {
            return format;
        }
    
        // It's better cut long arg for formating.
        for (int i = 0; i < args.Length; i++)
        {
            string arg = args[i] as string;
            if ((arg != null) && (arg.Length > 0x400))
            {
                args[i] = arg.Substring(0, 0x3fd) + "";
            }
        }
        return string.Format(System.Globalization.CultureInfo.CurrentCulture, format, args);
    }

    OK,大功告成,有了这么一个封装,在应用里就可以简单的这么几句够搞定。

    private void Form1_Load(object sender, EventArgs e)
    {
        this.comboBox1.DataSource = new EnumDataSource<Sex>();
        this.comboBox1.DisplayMember = "DisplayValue";
        this.comboBox1.ValueMember = "Value";
    }
    
    public enum Sex
    {
        Male,
        Female
    }


    本文是由葡萄城技术开发团队发布,转载请注明出处:葡萄城官网


  • 相关阅读:
    白话经典算法系列之六 高速排序 高速搞定
    簡單SQL存儲過程實例
    ACE编译运行错误解决
    shell之变量与read
    Java实现第八届蓝桥杯魔方状态
    Java实现第八届蓝桥杯魔方状态
    Java实现第八届蓝桥杯魔方状态
    Java实现第八届蓝桥杯魔方状态
    Java实现第八届蓝桥杯购物单
    Java实现第八届蓝桥杯购物单
  • 原文地址:https://www.cnblogs.com/powertoolsteam/p/1773865.html
Copyright © 2020-2023  润新知