Атрибут DisplayName из ресурсов?
у меня есть локализованное приложение, и мне интересно, можно ли иметь DisplayName для определенного набора свойств модели из ресурса.
Я хотел бы сделать что-то вроде этого:
public class MyModel {
[Required]
[DisplayName(Resources.Resources.labelForName)]
public string name{ get; set; }
}
но я не могу этого сделать, так как компилятор говорит: "аргумент атрибута должен быть постоянным выражением, выражением типа typeof или выражением создания массива типа параметра атрибута": (
есть ли обходные пути? Я выводю метки вручную, но мне нужно это для выхода валидатора!
6 ответов:
Как насчет написания пользовательских атрибутов:
public class LocalizedDisplayNameAttribute: DisplayNameAttribute { public LocalizedDisplayNameAttribute(string resourceId) : base(GetMessageFromResource(resourceId)) { } private static string GetMessageFromResource(string resourceId) { // TODO: Return the string from the resource file } }, который может быть использован такой:
public class MyModel { [Required] [LocalizedDisplayName("labelForName")] public string Name { get; set; } }
если вы используете MVC 3 и .NET 4, Вы можете использовать новый
DisplayнаSystem.ComponentModel.DataAnnotationsпространство имен. Этот атрибут заменяетDisplayNameатрибут и обеспечивает гораздо больше функциональности, включая поддержку локализации.в вашем случае, вы бы использовали его так:
public class MyModel { [Required] [Display(Name = "labelForName", ResourceType = typeof(Resources.Resources))] public string name{ get; set; } }как Примечание стороны, этот атрибут не будет работать с ресурсами внутри
App_GlobalResourcesилиApp_LocalResources. Это связано с пользовательским инструментом (GlobalResourceProxyGenerator) эти ресурсы использовать. Вместо того, чтобы сделать файл ресурсов имеет значение внедренный ресурс и использовать ResXFileCodeGenerator' специальный инструмент.(в качестве примечания, вы не должны использовать
App_GlobalResourcesилиApp_LocalResourcesС MVC. Вы можете узнать больше о том, почему это так здесь)
Если вы откроете файл ресурсов и измените модификатор доступа на public или internal, он создаст класс из вашего файла ресурсов, который позволит вам создавать строго типизированные ссылки на ресурсы.
что означает, что вы можете сделать что-то вроде этого (с использованием C# 6.0). Тогда вам не нужно помнить, было ли firstname в нижнем регистре или camelcased. И вы можете увидеть, если другие свойства используют то же значение ресурса с найти все ссылки на литературу.
[Display(Name = nameof(PropertyNames.FirstName), ResourceType = typeof(PropertyNames))] public string FirstName { get; set; }
обновление:
Я знаю, что уже слишком поздно, но я хотел бы добавить это обновление:
Я использую Поставщик Метаданных Обычной Модели, который представил Фил Haacked это более мощный и простой в применении взгляните на него : ConventionalModelMetadataProvider
Ответ
здесь Если вы хотите поддержать много типов ресурсы:
public class LocalizedDisplayNameAttribute : DisplayNameAttribute { private readonly PropertyInfo nameProperty; public LocalizedDisplayNameAttribute(string displayNameKey, Type resourceType = null) : base(displayNameKey) { if (resourceType != null) { nameProperty = resourceType.GetProperty(base.DisplayName, BindingFlags.Static | BindingFlags.Public); } } public override string DisplayName { get { if (nameProperty == null) { return base.DisplayName; } return (string)nameProperty.GetValue(nameProperty.DeclaringType, null); } } }тогда используйте его так:
[LocalizedDisplayName("Password", typeof(Res.Model.Shared.ModelProperties))] public string Password { get; set; }полный учебник по локализации см. на этой странице.
Я получил ответ Gunders, работающий с моими App_GlobalResources, выбрав Свойства ресурсов и переключив "пользовательский инструмент" на "PublicResXFileCodeGenerator" и создав действие "встроенный ресурс". Пожалуйста, обратите внимание на комментарий Gunders ниже.
работает как шарм :)
public class Person { // Before C# 6.0 [Display(Name = "Age", ResourceType = typeof(Testi18n.Resource))] public string Age { get; set; } // After C# 6.0 // [Display(Name = nameof(Resource.Age), ResourceType = typeof(Resource))] }
- определение Тип_ресурса атрибута, поэтому он ищет ресурс
определение имя атрибута, который используется для ключа ресурса, после C# 6.0, вы можете использовать
nameofдля сильной типизированной поддержки вместо жесткого кодирования ключа.установите культуру текущего потока в контроллере.
Resource.Culture = CultureInfo.GetCultureInfo("zh-CN");
установить доступность ресурса для общественности
отображение метки в cshtml такой
@Html.DisplayNameFor(model => model.Age)


Comments