Атрибут DisplayName из ресурсов?



у меня есть локализованное приложение, и мне интересно, можно ли иметь DisplayName для определенного набора свойств модели из ресурса.



Я хотел бы сделать что-то вроде этого:



public class MyModel {
[Required]
[DisplayName(Resources.Resources.labelForName)]
public string name{ get; set; }
}


но я не могу этого сделать, так как компилятор говорит: "аргумент атрибута должен быть постоянным выражением, выражением типа typeof или выражением создания массива типа параметра атрибута": (



есть ли обходные пути? Я выводю метки вручную, но мне нужно это для выхода валидатора!

636   6  

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, он создаст класс из вашего файла ресурсов, который позволит вам создавать строго типизированные ссылки на ресурсы.

Option for resource file code generation

что означает, что вы можете сделать что-то вроде этого (с использованием 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 ниже.

enter image description here

работает как шарм :)

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))]
}
  1. определение Тип_ресурса атрибута, поэтому он ищет ресурс
  2. определение имя атрибута, который используется для ключа ресурса, после C# 6.0, вы можете использовать nameof для сильной типизированной поддержки вместо жесткого кодирования ключа.

  3. установите культуру текущего потока в контроллере.

Resource.Culture = CultureInfo.GetCultureInfo("zh-CN");

  1. установить доступность ресурса для общественности

  2. отображение метки в cshtml такой

@Html.DisplayNameFor(model => model.Age)

Comments

    Ничего не найдено.