bza*_*fir 21 .net c# enums localization naming-conventions
我有一个类似的枚举
Enum Complexity
{
NotSoComplex,
LittleComplex,
Complex,
VeryComplex
}
Run Code Online (Sandbox Code Playgroud)
我想在下拉列表中使用它,但不希望在列表中看到这样的Camel名称(对用户来说看起来很奇怪).相反,我希望有正常的措辞,如不那么复杂的小复杂(等)
此外,我的应用程序是多语言,我希望能够显示这些字符串本地化,我使用帮助器,TranslationHelper(字符串strID),它给我一个字符串ID的本地化版本.
我有一个工作的解决方案,但不是很优雅:我为枚举创建一个辅助类,其中一个成员Complexity和ToString()被覆盖,如下所示(代码简化)
public class ComplexityHelper
{
public ComplexityHelper(Complexity c, string desc)
{ m_complex = c; m_desc=desc; }
public Complexity Complexity { get { ... } set {...} }
public override ToString() { return m_desc; }
//Then a static field like this
private static List<Complexity> m_cxList = null;
// and method that returns the status lists to bind to DataSource of lists
public static List<ComplexityHelper> GetComplexities()
{
if (m_cxList == null)
{
string[] list = TranslationHelper.GetTranslation("item_Complexities").Split(',');
Array listVal = Enum.GetValues(typeof(Complexities));
if (list.Length != listVal.Length)
throw new Exception("Invalid Complexities translations (item_Complexities)");
m_cxList = new List<Complexity>();
for (int i = 0; i < list.Length; i++)
{
Complexity cx = (ComplexitylistVal.GetValue(i);
ComplexityHelper ch = new ComplexityHelper(cx, list[i]);
m_cxList.Add(ch);
}
}
return m_cxList;
}
}
Run Code Online (Sandbox Code Playgroud)
虽然可行,但我对此并不满意,因为我必须对我需要在选项列表中使用的各种枚举进行类似编码.
有没有人建议更简单或更通用的解决方案?
谢谢波格丹
Rex*_*x M 62
基本友好名称
enum MyEnum
{
[Description("This is black")]
Black,
[Description("This is white")]
White
}
Run Code Online (Sandbox Code Playgroud)
和枚举的一个方便的扩展方法:
public static string GetDescription(this Enum value)
{
FieldInfo field = value.GetType().GetField(value.ToString());
object[] attribs = field.GetCustomAttributes(typeof(DescriptionAttribute), true);
if(attribs.Length > 0)
{
return ((DescriptionAttribute)attribs[0]).Description;
}
return string.Empty;
}
Run Code Online (Sandbox Code Playgroud)
像这样使用:
MyEnum val = MyEnum.Black;
Console.WriteLine(val.GetDescription()); //writes "This is black"
Run Code Online (Sandbox Code Playgroud)
(注意这对位标志不起作用......)
用于本地化
.NET中有一个完善的模式,用于处理每个字符串值的多种语言 - 使用资源文件,并展开扩展方法以从资源文件中读取:
public static string GetDescription(this Enum value)
{
FieldInfo field = value.GetType().GetField(value.ToString());
object[] attribs = field.GetCustomAttributes(typeof(DescriptionAttribute), true));
if(attribs.Length > 0)
{
string message = ((DescriptionAttribute)attribs[0]).Description;
return resourceMgr.GetString(message, CultureInfo.CurrentCulture);
}
return string.Empty;
}
Run Code Online (Sandbox Code Playgroud)
任何时候我们都可以利用现有的BCL功能来实现我们想要的,这绝对是第一个探索的途径.这样可以最大限度地降低复杂性,并使用许多其
把它们放在一起
为了将其绑定到DropDownList,我们可能希望跟踪控件中的实际枚举值,并将已翻译的友好名称限制为可视糖.我们可以通过在列表中使用匿名类型和DataField属性来实现:
<asp:DropDownList ID="myDDL"
DataTextField="Description"
DataValueField="Value" />
myDDL.DataSource = Enum.GetValues(typeof(MyEnum)).OfType<MyEnum>().Select(
val => new { Description = val.GetDescription(), Value = val.ToString() });
myDDL.DataBind();
Run Code Online (Sandbox Code Playgroud)
让我们分解一下DataSource行:
Enum.GetValues(typeof(MyEnum)),它给我们一个松散类型Array的价值观OfType<MyEnum>()将数组转换为aIEnumerable<MyEnum>Select()并提供一个lambda,它使用两个字段Description和Value来投影一个新对象.DataTextField和DataValueField属性在数据绑定时反复评估,因此它们将在DataItem上搜索具有匹配名称的字段.
- 请注意,在主要文章中,作者编写了自己的DescriptionAttribute类,这是不必要的,因为.NET的标准库中已经存在.-
像在其他答案中一样使用属性是一个不错的方法,但是,如果您只想使用枚举值中的文本,则以下代码将根据值的驼峰式大小进行拆分:
public static string GetDescriptionOf(Enum enumType)
{
Regex capitalLetterMatch = new Regex("\\B[A-Z]", RegexOptions.Compiled);
return capitalLetterMatch.Replace(enumType.ToString(), " $&");
}
Run Code Online (Sandbox Code Playgroud)
呼叫GetDescriptionOf(Complexity.NotSoComplex)将返回Not So Complex。可以与任何枚举值一起使用。
为了使其更有用,您可以使其成为扩展方法:
public static string ToFriendlyString(this Enum enumType)
{
Regex capitalLetterMatch = new Regex("\\B[A-Z]", RegexOptions.Compiled);
return capitalLetterMatch.Replace(enumType.ToString(), " $&");
}
Run Code Online (Sandbox Code Playgroud)
您现在可以使用Complexity.NotSoComplex.ToFriendlyString()return来调用它Not So Complex。
编辑:刚注意到,在您的问题中,您提到需要本地化文本。在那种情况下,我将使用一个属性来包含一个键来查找本地化的值,但是如果找不到本地化的文本,则默认使用友好的字符串方法作为最后的选择。您可以这样定义您的枚举:
enum Complexity
{
[LocalisedEnum("Complexity.NotSoComplex")]
NotSoComplex,
[LocalisedEnum("Complexity.LittleComplex")]
LittleComplex,
[LocalisedEnum("Complexity.Complex")]
Complex,
[LocalisedEnum("Complexity.VeryComplex")]
VeryComplex
}
Run Code Online (Sandbox Code Playgroud)
您还需要以下代码:
[AttributeUsage(AttributeTargets.Field, AllowMultiple=false, Inherited=true)]
public class LocalisedEnum : Attribute
{
public string LocalisationKey{get;set;}
public LocalisedEnum(string localisationKey)
{
LocalisationKey = localisationKey;
}
}
public static class LocalisedEnumExtensions
{
public static string ToLocalisedString(this Enum enumType)
{
// default value is the ToString();
string description = enumType.ToString();
try
{
bool done = false;
MemberInfo[] memberInfo = enumType.GetType().GetMember(enumType.ToString());
if (memberInfo != null && memberInfo.Length > 0)
{
object[] attributes = memberInfo[0].GetCustomAttributes(typeof(LocalisedEnum), false);
if (attributes != null && attributes.Length > 0)
{
LocalisedEnum descriptionAttribute = attributes[0] as LocalisedEnum;
if (description != null && descriptionAttribute != null)
{
string desc = TranslationHelper.GetTranslation(descriptionAttribute.LocalisationKey);
if (desc != null)
{
description = desc;
done = true;
}
}
}
}
if (!done)
{
Regex capitalLetterMatch = new Regex("\\B[A-Z]", RegexOptions.Compiled);
description = capitalLetterMatch.Replace(enumType.ToString(), " $&");
}
}
catch
{
description = enumType.ToString();
}
return description;
}
}
Run Code Online (Sandbox Code Playgroud)
要获取本地化的描述,请致电:
Complexity.NotSoComplex.ToLocalisedString()
Run Code Online (Sandbox Code Playgroud)
这有几种后备情况:
LocalisedEnum定义了属性,它将使用该键查找翻译的文本LocalisedEnum定义属性,但未找到本地化文本,则默认使用驼峰式拆分方法LocalisedEnum定义属性,它将使用驼峰分割方法谢谢大家的所有回答。最后,我使用了 Rex M 和 adrianbanks 的组合,并添加了我自己的改进,以简化与 ComboBox 的绑定。
需要进行这些更改是因为,在处理代码时,我意识到有时需要能够从组合中排除一个枚举项。例如
Enum Complexity
{
// this will be used in filters,
// but not in module where I have to assign Complexity to a field
AllComplexities,
NotSoComplex,
LittleComplex,
Complex,
VeryComplex
}
Run Code Online (Sandbox Code Playgroud)
因此,有时我希望选项列表显示除所有复杂性之外的所有复杂性(在添加 - 编辑模块中),而其他时间则显示所有复杂性(在过滤器中)
这就是我所做的:
完整代码如下所示
public static string GetDescription(this System.Enum value)
{
string enumID = string.Empty;
string enumDesc = string.Empty;
try
{
// try to lookup Description attribute
FieldInfo field = value.GetType().GetField(value.ToString());
object[] attribs = field.GetCustomAttributes(typeof(DescriptionAttribute), true);
if (attribs.Length > 0)
{
enumID = ((DescriptionAttribute)attribs[0]).Description;
enumDesc = TranslationHelper.GetTranslation(enumID);
}
if (string.IsNullOrEmpty(enumID) || TranslationHelper.IsTranslationMissing(enumDesc))
{
// try to lookup translation from EnumName_EnumValue
string[] enumName = value.GetType().ToString().Split('.');
enumID = string.Format("{0}_{1}", enumName[enumName.Length - 1], value.ToString());
enumDesc = TranslationHelper.GetTranslation(enumID);
if (TranslationHelper.IsTranslationMissing(enumDesc))
enumDesc = string.Empty;
}
// try to format CamelCase to proper names
if (string.IsNullOrEmpty(enumDesc))
{
Regex capitalLetterMatch = new Regex("\\B[A-Z]", RegexOptions.Compiled);
enumDesc = capitalLetterMatch.Replace(value.ToString(), " $&");
}
}
catch (Exception)
{
// if any error, fallback to string value
enumDesc = value.ToString();
}
return enumDesc;
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个基于 Enum 的通用帮助器类,它允许将枚举轻松绑定到数据源
public class LocalizableEnum
{
/// <summary>
/// Column names exposed by LocalizableEnum
/// </summary>
public class ColumnNames
{
public const string ID = "EnumValue";
public const string EntityValue = "EnumDescription";
}
}
public class LocalizableEnum<T>
{
private T m_ItemVal;
private string m_ItemDesc;
public LocalizableEnum(T id)
{
System.Enum idEnum = id as System.Enum;
if (idEnum == null)
throw new ArgumentException(string.Format("Type {0} is not enum", id.ToString()));
else
{
m_ItemVal = id;
m_ItemDesc = idEnum.GetDescription();
}
}
public override string ToString()
{
return m_ItemDesc;
}
public T EnumValue
{
get { return m_ID; }
}
public string EnumDescription
{
get { return ToString(); }
}
}
Run Code Online (Sandbox Code Playgroud)
然后我创建了一个返回 List> 的通用静态方法,如下所示
public static List<LocalizableEnum<T>> GetEnumList<T>(object excludeMember)
{
List<LocalizableEnum<T>> list =null;
Array listVal = System.Enum.GetValues(typeof(T));
if (listVal.Length>0)
{
string excludedValStr = string.Empty;
if (excludeMember != null)
excludedValStr = ((T)excludeMember).ToString();
list = new List<LocalizableEnum<T>>();
for (int i = 0; i < listVal.Length; i++)
{
T currentVal = (T)listVal.GetValue(i);
if (excludedValStr != currentVal.ToString())
{
System.Enum enumVal = currentVal as System.Enum;
LocalizableEnum<T> enumMember = new LocalizableEnum<T>(currentVal);
list.Add(enumMember);
}
}
}
return list;
}
Run Code Online (Sandbox Code Playgroud)
和一个返回包含所有成员的列表的包装器
public static List<LocalizableEnum<T>> GetEnumList<T>()
{
return GetEnumList<T>(null);
}
Run Code Online (Sandbox Code Playgroud)
现在让我们把所有东西放在一起并绑定到实际的组合:
// in module where we want to show items with all complexities
// or just filter on one complexity
comboComplexity.DisplayMember = LocalizableEnum.ColumnNames.EnumValue;
comboComplexity.ValueMember = LocalizableEnum.ColumnNames.EnumDescription;
comboComplexity.DataSource = EnumHelper.GetEnumList<Complexity>();
comboComplexity.SelectedValue = Complexity.AllComplexities;
// ....
// and here in edit module where we don't want to see "All Complexities"
comboComplexity.DisplayMember = LocalizableEnum.ColumnNames.EnumValue;
comboComplexity.ValueMember = LocalizableEnum.ColumnNames.EnumDescription;
comboComplexity.DataSource = EnumHelper.GetEnumList<Complexity>(Complexity.AllComplexities);
comboComplexity.SelectedValue = Complexity.VeryComplex; // set default value
Run Code Online (Sandbox Code Playgroud)
要读取选定的值并使用它,我使用如下代码
Complexity selComplexity = (Complexity)comboComplexity.SelectedValue;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10247 次 |
| 最近记录: |