在.net中本地化枚舉描述的最佳方式是什麼?本地化枚舉描述屬性
(用於枚舉描述例如見Adding descriptions to enumeration constants)
理想我想的東西,使用的ResourceManager和資源文件,因此它適合於如何應用的其他部分是局部的。
在.net中本地化枚舉描述的最佳方式是什麼?本地化枚舉描述屬性
(用於枚舉描述例如見Adding descriptions to enumeration constants)
理想我想的東西,使用的ResourceManager和資源文件,因此它適合於如何應用的其他部分是局部的。
這是我結束了去,我沒有看到添加自定義屬性的值類舉行資源鍵,然後查找資源文件 - 爲什麼不使用枚舉typename +值作爲資源鍵?
using System;
using System.Resources;
using System.Reflection;
public class MyClass
{
enum SomeEnum {Small,Large};
private ResourceManager _resources = new ResourceManager("MyClass.myResources",
System.Reflection.Assembly.GetExecutingAssembly());
public string EnumDescription(Enum enumerator)
{
string rk = String.Format("{0}.{1}",enumerator.GetType(),enumerator);
string localizedDescription = _resources.GetString(rk);
if (localizedDescription == null)
{
// A localized string was not found so you can either just return
// the enums value - most likely readable and a good fallback.
return enumerator.ToString();
// Or you can return the full resourceKey which will be helpful when
// editing the resource files(e.g. MyClass+SomeEnum.Small)
// return resourceKey;
}
else
return localizedDescription;
}
void SomeRoutine()
{
// Looks in resource file for a string matching the key
// "MyClass+SomeEnum.Large"
string s1 = EnumDescription(SomeEnum.Large);
}
}
有一個簡單的解決方案: 使用LocalizedDescription屬性來傳遞資源密鑰。
[Serializable]
public class LocalizableDescriptionAttribute:DescriptionAttribute
{
public LocalizableDescriptionAttribute(string resourceKey)
:base(Resources.ResourceManager.GetString(resourceKey))
{ }
}
見我的表例如,在這樣一個問題:
Localisation/I18n of database data in LINQ to SQL
的狀態類型表映射到枚舉值。這裏真正的好處是,您可以在報告和應用程序中進行本地化,並指定外部ID以與不想要內部值的第三方進行集成等。它將枚舉描述與其值進行分離。
以數據庫爲中心的應用程序的好方法,但真正矯枉過正滿足我的需求。 – Ryan 2009-02-20 13:53:32
不能應用多個System.ComponentModel.DescriptionAttribute(以便選項不可用)。
因此,添加一個間接級別,該描述包含資源名稱,然後在資源中使用本地化支持。很明顯,這個枚舉的用戶需要調用你的幫助器方法來完成這個任務。
這就是Valentin Vasiliev提出的建議,但不需要使用輔助方法 - 同樣的評論也適用。 – Ryan 2009-02-20 13:55:37
我做過一次的一種方法是在相同的命名空間中添加一個擴展方法作爲返回字符串的枚舉。在我的情況下,它只是硬編碼,但從資源文件中獲取它們並沒有問題。
public static string Describe(this SomeEnum e)
{
switch(e)
{
SomeEnum.A:
return "Some text from resourcefile";
SomeEnum.B:
return "Some other text from resourcefile";
...:
return ...;
}
}
也許不是一個平滑的極端花哨或解決方案,但它工作=)
我的解決方案,使用本地能解密屬性:
public class LocalizedEnumAttribute : DescriptionAttribute
{
private PropertyInfo _nameProperty;
private Type _resourceType;
public LocalizedEnumAttribute(string displayNameKey)
: base(displayNameKey)
{
}
public Type NameResourceType
{
get
{
return _resourceType;
}
set
{
_resourceType = value;
_nameProperty = _resourceType.GetProperty(this.Description, BindingFlags.Static | BindingFlags.Public);
}
}
public override string Description
{
get
{
//check if nameProperty is null and return original display name value
if (_nameProperty == null)
{
return base.Description;
}
return (string)_nameProperty.GetValue(_nameProperty.DeclaringType, null);
}
}
}
public static class EnumExtender
{
public static string GetLocalizedDescription(this Enum @enum)
{
if (@enum == null)
return null;
string description = @enum.ToString();
FieldInfo fieldInfo = @enum.GetType().GetField(description);
DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Any())
return attributes[0].Description;
return description;
}
}
枚舉聲明
public enum MyEnum
{
[LocalizedEnum("ResourceName", NameResourceType = typeof(ResourceType))]
Test = 0
}
然後調用MyEnumInstance.GetLocalizedDescription()
用以下內容替換@ nairik的方法以添加對標誌枚舉的支持。
public static string GetLocalizedDescription(this Enum @enum)
{
if (@enum == null)
return null;
StringBuilder sbRet = new StringBuilder();
string description = @enum.ToString();
var fields = description.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var field in fields)
{
FieldInfo fieldInfo = @enum.GetType().GetField(field);
DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Any())
sbRet.AppendFormat("{0}, ", attributes[0].Description);
else
sbRet.AppendFormat("{0}, ", field);
}
if (sbRet.Length > 2)
sbRet.Remove(sbRet.Length - 2, 2);
return sbRet.ToString();
}
,並在屬性替換NameResourceType:
public Type NameResourceType
{
get
{
return _resourceType;
}
set
{
_resourceType = value;
_nameProperty = _resourceType.GetProperty(base.Description, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
}
}
我不知道這是什麼讓你在使用枚舉類型的全名(namespace.enumname.value)作爲獲取ResourceKey。這似乎是一個額外的不必要的步驟(使用反射來獲得LocalizableDescriptionAttribute)只是去resourceManager - 我錯過了什麼? – Ryan 2009-02-20 13:59:23
我想我們有一個誤解。我使用我的屬性來本地化枚舉值描述。我想你說的是本地化枚舉而不是它們的價值。 – Valentin 2009-02-20 14:39:31
您不能用Description屬性裝飾枚舉值並傳遞資源鍵。 – Valentin 2009-02-20 14:41:26