65.9K
CodeProject 正在变化。 阅读更多。
Home

本地化 .NET 枚举

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (101投票s)

2007年8月9日

CPOL

6分钟阅读

viewsIcon

354153

downloadIcon

3805

描述了一种用于显示枚举本地化文本的技术

引言

枚举在 .NET 中的一个很酷的特性是,您可以使用数据绑定来在列表或下拉组合框中显示和选择枚举值。例如,考虑以下枚举定义:

enum SampleEnum
{
    VerySmall,
    Small,
    Medium,
    Large,
    VeryLarge
}

我们可以通过在窗体中添加一个 ListBox 并用一行代码设置 DataSource 来显示枚举值(并允许用户选择一个值)。

_enumListBox.DataSource = Enum.GetValues(typeof(SampleEnum));

这很棒——现在运行代码时,列表框会显示枚举值。

Screenshot - EnumList.jpg

我们可以通过简单地使用列表框的 SelectedItem 属性来获取选定的 enum 值。

SampleEnum selectedSampleEnum = (SampleEnum)_enumListBox.SelectedItem;

但是,此技术存在两个问题。第一个问题是,我们希望显示的文本可能与枚举值不完全相同。在上面的示例中,显示 Very Small 并带有空格会更好。但是,我们不能使用这个作为枚举值,因为 enum 值不能包含空格。第二个问题是,如果我们想本地化应用程序(即为不同语言提供本地化的用户界面),则无法翻译枚举值。

本文提出了一种利用 .NET TypeConverter 功能的简单解决方案来解决上述问题。

背景

Alex Kolesnichenko 的文章 Humanizing the Enumerations 也讨论了上述问题,通过为每个枚举值附加一个自定义属性,并使用适配器类 (EnumToHumanReadableConverter) 作为数据源。我们的方法则利用 .NET TypeConverter 机制的功能,自动处理到本地化文本和 enum 值之间的转换。此方法的优点不仅在于它适用于数据绑定(无需额外代码),还可以在应用程序中任何需要本地化文本和 enum 值之间转换的地方使用。

什么是 TypeConverter?

TypeConverter 是 .NET 的内置机制,用于将一种类型的对象转换为另一种类型(例如,从 enum 值转换为 string 值)。当 ListBox 控件(和其他 .NET 控件)显示 enum 值时,它会首先使用 TypeConverter 将它们转换为 string。它使用的 TypeConverter 取决于通过 System.ComponentModel.TypeConverterAttribute 与类型关联的 TypeConverter。默认情况下,所有 enum 类型都使用预定义的 EnumConverter 类。正如我们所见,EnumConverter 只是将 enum 值转换为其精确的 string 表示形式。幸运的是,我们可以定义自己的派生 TypeConverter 类,并在声明它时将其与我们的 enum 类型关联,如下所示:

[TypeConverter(typeof(LocalizedEnumConverter))]
public enum SampleEnum
{
    VerySmall,
    Small,
    Medium,
    Large,
    VeryLarge
}

在此解决方案中,我们定义了一个自定义 TypeConverter 类 (LocalizedEnumConverter),它使用项目资源中的本地化 string 来将 enum 值与 string 值进行转换。

Using the Code

示例项目代码包含一个库 (Infralution.Localization) 和一个单独的测试应用程序。该库定义了一个基类 TypeConverter (ResourceEnumConverter),它使用 ResourceManagerenum 值与 string 进行转换,该 ResourceManager 从已编译的 RESX 文件中读取 string 值。用于执行查找的 ResourceManager 被传递给 ResourceEnumConverter 类的构造函数。请遵循以下简单步骤,在应用程序中使用此类本地化 enum

在应用程序项目中定义一个派生自 ResourceEnumConverter 的类,该类传递用于枚举查找的 RESX 项目文件的 ResourceManager。通常,您只需使用标准的项目 Properties.Resources

class LocalizedEnumConverter : Infralution.Localization.ResourceEnumConverter
{
    public LocalizedEnumConverter(Type type)
        : base(type, Properties.Resources.ResourceManager)
    {
    }
}

在每个 enum 声明上使用 System.ComponentModel.TypeConverterAttribute 属性将此 TypeConverterenum 关联。

[TypeConverter(typeof(LocalizedEnumConverter))]
public enum SampleEnum
{
    VerySmall,
    Small,
    Medium,
    Large,
    VeryLarge
}

在资源编辑器中打开 _Properties\Resources.resx_ 文件,然后输入要为每个 enum 值显示的文本。资源名称就是 enum 类型名称后跟值(下划线分隔)。

Screenshot - EnglishResx.jpg

现在我们可以添加一些本地化的 enum 文本值了。通过将 _Properties\Resources.resx_ 文件复制到 _Properties\Resources.fr.resx_ 来创建一个法语资源集。请确保此新 RESX 文件的“自定义工具”(在属性窗口中)为空,否则您将遇到一些奇怪的编译错误。在资源编辑器中打开 _Properties\Resources.fr.resx_ 文件,然后输入翻译后的值。

Screenshot - FrenchResx.jpg

现在,使用控制面板的区域选项将用户区域设置为法语,然后运行您的应用程序。enum 值现在以法语显示。示例应用程序演示了上述内容,还允许您通过从下拉列表中选择来动态设置 CurrentThread.CurrentCulture 属性。

Screenshot - SampleApp.jpg

ResourceEnumConverter 类还支持将文本值转换回 enum 值。示例应用程序允许您通过在文本框中输入值并单击 Convert 按钮来测试这一点。

在 ASP.NET 中本地化枚举

在 Windows Forms 中,所有标准控件都使用 TypeConverters 将绑定数据值转换为显示字符串。不幸的是,由于某些原因,Microsoft 在开发 ASP.NET 控件时并未采用这种方法。ASP.NET 控件通常只使用 Object.ToString() 方法将绑定数据值转换为文本。这意味着,虽然我们仍然可以定义我们的 TypeConverter(如上所述),但 ASP.NET 控件默认不会使用它。

为了解决这个问题,我们在 ResourceEnumConverter 类中添加了一个静态的 GetValues 方法。此方法使用 TypeConverter 返回给定 enum 类型的 KeyValuePair 对象列表。Keyenum 值,Value 是该 enum 的本地化显示文本。要绑定 ASP.NET 控件,我们将控件的 DataValueField 属性设置为 Key,将 DataTextField 属性设置为 Value。然后,我们像这样将控件绑定到 GetValues 方法返回的列表:

protected void Page_Load(object sender, EventArgs e)
{
    _enumListBox.DataSource = 
        LocalizedEnumConverter.GetValues(typeof(SampleEnum));
    this.DataBind();
}

标志枚举

Andy Mase 指出,原始代码未处理位字段枚举(使用 Flag 属性定义)。在这种情况下,枚举值可以是命名枚举值的按位组合。枚举还可以定义作为其他命名值按位组合的命名枚举值。在下面的示例中,定义了一个 All 值,它是所有其他值的按位组合。

[TypeConverter(typeof(LocalizedEnumConverter))]
[Flags]
public enum TextStyle : byte
{
    None = 0x0,
    Bold = 0x1,
    Italic = 0x2,
    Underline = 0x4,
    All = 0xFF
}

ResourceEnumConverter 类现在支持将位字段 enum 与文本进行相互转换。在将位字段 enum 值转换为文本时,它首先检查该值是否是命名枚举值之一。如果是,则使用与命名值对应的本地化文本。否则,它会找到设置的单比特值的组合,并通过连接这些值的本地化文本来创建文本。例如,值 0x3 将在英语中转换为 Bold, Italic。下载现在包含一个单独的项目 (TestLocalizedFlagEnum),演示了如何在位字段 enum 中使用 LocalizedEnumConverter

历史

  • 2007.08.09 - 初次发布
  • 2007.10.17 - 添加了对标志 enum 的处理以及 ASP.NET 中 enum 的本地化。
© . All rights reserved.