Quo*_*ter 53 c# localization asp.net-mvc-4
如何ListBoxFor在可能有多个选项的地方枚举枚举?
例如enum,包含角色:
public enum RoleType
{
[Display(Description = "Administrator", ResourceType = typeof(Resource))]
Administrator = 1,
[Display(Description = "Moderator", ResourceType = typeof(Resource))]
Moderator = 2,
[Display(Description = "Webmaster", ResourceType = typeof(Resource))]
Webmaster = 3,
[Display(Description = "Guest", ResourceType = typeof(Resource))]
Guest = 4,
Etc.... = 5,
}
Run Code Online (Sandbox Code Playgroud)
我已经看到用dropdownlist/ 完成了这个selectlists.但是有没有办法为多选列表执行此操作?
[编辑]
这就是我想要使用它的方式,它现在是如何工作的,但不会用其他语言翻译:
var roles = from role r in Enum.GetValues(typeof(RoleType))
select new
{
Id = (int)Enum.Parse(typeof(RoleType), r.ToString()),
Name = r.ToString()
};
searchModel.roles = new MultiSelectList(roles, "Id", "Name");
Run Code Online (Sandbox Code Playgroud)
注意:我已将"枚举"从"角色"重命名为"角色类型".
elu*_*xen 67
您可以实现描述属性.
public class LocalizedDescriptionAttribute : DescriptionAttribute
{
private readonly string _resourceKey;
private readonly ResourceManager _resource;
public LocalizedDescriptionAttribute(string resourceKey, Type resourceType)
{
_resource = new ResourceManager(resourceType);
_resourceKey = resourceKey;
}
public override string Description
{
get
{
string displayName = _resource.GetString(_resourceKey);
return string.IsNullOrEmpty(displayName)
? string.Format("[[{0}]]", _resourceKey)
: displayName;
}
}
}
public static class EnumExtensions
{
public static string GetDescription(this Enum enumValue)
{
FieldInfo fi = enumValue.GetType().GetField(enumValue.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute),
false);
if (attributes != null &&
attributes.Length > 0)
return attributes[0].Description;
else
return enumValue.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
像这样定义:
public enum Roles
{
[LocalizedDescription("Administrator", typeof(Resource))]
Administrator,
...
}
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
var roles = from RoleType role in Enum.GetValues(typeof(RoleType))
select new
{
Id = (int)role,
Name = role.GetDescription()
};
searchModel.roles = new MultiSelectList(roles, "Id", "Name");
Run Code Online (Sandbox Code Playgroud)
dis*_*sco 30
我通过创建一个我在视图中使用的EnumExtension解决了这个问题.此扩展名查找名为"EnumResources.resx"的资源文件,并通过以下命名约定{EnumType的名称} _ {传入的枚举值}来查找资源.如果缺少资源键,它将显示封装在双括号[[EnumValue]]中的资源的值.这样很容易在你的视图中找到一个"未翻译的"枚举.这也有助于提醒您是否忘记在重命名后更新资源文件等.
public static class EnumExtensions
{
public static string GetDisplayName(this Enum e)
{
var rm = new ResourceManager(typeof (EnumResources));
var resourceDisplayName = rm.GetString(e.GetType().Name + "_" + e);
return string.IsNullOrWhiteSpace(resourceDisplayName) ? string.Format("[[{0}]]", e) : resourceDisplayName;
}
}
Run Code Online (Sandbox Code Playgroud)
资源文件如下所示:

用法:
<div>@ContractStatus.Created.GetDisplayName()</div>
Run Code Online (Sandbox Code Playgroud)
Ber*_* IT 13
现在它很简单,设置你的枚举:
public enum ContactOptionType
{
[Display(Description = "ContactOption1", ResourceType = typeof(Globalization.Contact))]
Demo = 1,
[Display(Description = "ContactOption2", ResourceType = typeof(Globalization.Contact))]
Callback = 2,
[Display(Description = "ContactOption3", ResourceType = typeof(Globalization.Contact))]
Quotation = 3,
[Display(Description = "ContactOption4", ResourceType = typeof(Globalization.Contact))]
Other = 4
}
Run Code Online (Sandbox Code Playgroud)
每个枚举值都有一个值,Display attribute该Description值是名为 的资源程序集类中的一个条目Globalization.Contact。此资源程序集(项目)包含不同联系选项类型(演示、回调、报价、其他)的各种翻译。它包含如下文件:(contact.nl.resx对于荷兰)和contact.resx(默认为 en-US),其中不同的枚举值具有其本地化值(翻译)。
现在在一个静态枚举助手类中,我们有这个方法:
public static string GetDisplayDescription(this Enum enumValue)
{
return enumValue.GetType().GetMember(enumValue.ToString())
.FirstOrDefault()?
.GetCustomAttribute<DisplayAttribute>()
.GetDescription() ?? "unknown";
}
Run Code Online (Sandbox Code Playgroud)
这将获得Description属性的Display属性值。当且仅当CurrentUICulture被设置时,这将是翻译后的值。这将所有东西“粘合”在一起。
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
Run Code Online (Sandbox Code Playgroud)
或者
Thread.CurrentThread.CurrentUICulture = new CultureInfo("nl-NL");
Run Code Online (Sandbox Code Playgroud)
现在在一个简单的单元测试 (XUnit) 中,我们可以查看它是否按预期/期望/设计工作:
[Theory]
[InlineData("nl-NL", "Terugbelverzoek")]
[InlineData("en-US", "Callback")]
public void TestTranslationOfDescriptionAttribute(string culture, string expectedValue)
{
// Arrange
CultureInfo cultureInfo = new CultureInfo(culture);
Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;
ContactOptionType contactOptionType = ContactOptionType.Callback;
// Act
string description = contactOptionType.GetDisplayDescription();
// Assert
Assert.Equal(expectedValue, description);
}
Run Code Online (Sandbox Code Playgroud)
以上会毫不费力地成功???
因此,此解决方案不再使用“复杂” LocalizedAttribute,仅使用一个简单的帮助器来获取 Display 属性的 Description 属性的(翻译)值。ResourceTypeDisplay 属性中存在一个值并结合设置 可以解决CurrentUICulture问题。
有一种方法可以在显示时使用属性来指定用于枚举的字符串,但是当您必须处理本地化时,我们发现它太过于繁琐.
因此,我们通常为需要本地化的枚举做的是编写一个扩展类,它提供了获取翻译名称的方法.您可以使用从常用资源返回字符串的开关.这样,您可以通过资源为枚举提供翻译的字符串,就像您对其他字符串一样.
例如:
public enum Role
{
Administrator,
Moderator,
Webmaster,
Guest
}
public static class RoleExt
{
public static string AsDisplayString(this Role role)
{
switch (role)
{
case Role.Administrator: return Resources.RoleAdministrator;
case Role.Moderator: return Resources.RoleModerator;
case Role.Webmaster: return Resources.RoleWebmaster;
case Role.Guest: return Resources.RoleGuest;
default: throw new ArgumentOutOfRangeException("role");
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以这样使用:
var role = Role.Administrator;
Console.WriteLine(role.AsDisplayString());
Run Code Online (Sandbox Code Playgroud)
如果将RoleExt类实现保留在实现旁边,enum Role它将有效地成为接口的一部分Role.当然,您还可以为此类添加任何其他有用的枚举.
[编辑]
如果您想处理多个标志设置("管理员和主持人和网站管理员"),那么您需要做一些不同的事情:
[Flags]
public enum Roles
{
None = 0,
Administrator = 1,
Moderator = 2,
Webmaster = 4,
Guest = 8
}
public static class RolesExt
{
public static string AsDisplayString(this Roles roles)
{
if (roles == 0)
return Resources.RoleNone;
var result = new StringBuilder();
if ((roles & Roles.Administrator) != 0)
result.Append(Resources.RoleAdministrator + " ");
if ((roles & Roles.Moderator) != 0)
result.Append(Resources.RoleModerator + " ");
if ((roles & Roles.Webmaster) != 0)
result.Append(Resources.RoleWebmaster + " ");
if ((roles & Roles.Guest) != 0)
result.Append(Resources.RoleGuest + " ");
return result.ToString().TrimEnd();
}
}
Run Code Online (Sandbox Code Playgroud)
您可能会这样使用:
Roles roles = Roles.Administrator | Roles.Guest | Roles.Moderator;
Console.WriteLine(roles.AsDisplayString());
Run Code Online (Sandbox Code Playgroud)
资源文件
资源文件是您使字符串国际化的方式.有关如何使用它们的更多信息,请参见此处:
http://msdn.microsoft.com/en-us/library/vstudio/aa992030%28v=vs.100%29.aspx http://msdn.microsoft.com/en-us/library/vstudio/756hydy4%28v = VS.100%29.aspx