资源中的DisplayName属性?

Pal*_*tir 159 c# asp.net-mvc resources localization resx

我有一个本地化的应用程序,我想知道是否可以DisplayName从资源中设置某个模型属性.

我想做这样的事情:

public class MyModel {
  [Required]
  [DisplayName(Resources.Resources.labelForName)]
  public string name{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)

但是我不能这样,因为编译器说:"属性参数必须是常量表达式,typeof表达式或属性参数类型的数组创建表达式":(

有没有解决方法?我手动输出标签,但我需要这些用于验证器输出!

Ren*_*ené 369

如果使用MVC 3和.NET 4,则可以DisplaySystem.ComponentModel.DataAnnotations命名空间中使用new 属性.此属性替换DisplayName属性并提供更多功能,包括本地化支持.

在你的情况下,你会像这样使用它:

public class MyModel
{
    [Required]
    [Display(Name = "labelForName", ResourceType = typeof(Resources.Resources))]
    public string name{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)

作为旁注,此属性不适用于内部App_GlobalResourcesApp_LocalResources.这与GlobalResourceProxyGenerator这些资源使用的自定义工具()有关.而是确保您的资源文件设置为"嵌入式资源"并使用"ResXFileCodeGenerator"自定义工具.

(作为进一步的附注,你不应该使用App_GlobalResourcesApp_LocalResources使用MVC.你可以在这里阅读更多关于为什么会这样的情况)

  • 使用C#6,而不是`Name ="labelForName"`你也可以使用`Name = nameof(Resources.Resources.labelForName)`. (12认同)

Dar*_*rov 109

如何编写自定义属性:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

可以像这样使用:

public class MyModel 
{
    [Required]
    [LocalizedDisplayName("labelForName")]
    public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

  • @Gunder他的帖子,低于这个(投票最多),是一个更好的解决方案.仅适用于仅阅读已接受帖子的人士 (22认同)
  • 对TODO的建议:返回Resources.Language.ResourceManager.GetString(resourceId); (5认同)
  • 你应该使用:[Display(Name ="labelForName",ResourceType = typeof(Resources.Resources))]如下所述...... (4认同)

Tik*_*all 33

如果打开资源文件并将访问修饰符更改为public或internal,它将从资源文件生成一个类,允许您创建强类型资源引用.

资源文件代码生成选项

这意味着你可以做这样的事情(使用C#6.0).然后你不必记住firstname是小写还是camelcased.您可以看到其他属性是否使用相同的资源值和查找所有引用.

[Display(Name = nameof(PropertyNames.FirstName), ResourceType = typeof(PropertyNames))]
public string FirstName { get; set; }
Run Code Online (Sandbox Code Playgroud)

  • 您是否使用attribute.Name或attribute.GetName()来获取本地化文本?.Name的文档说"不要使用此属性来获取Name属性的值.请改用GetName方法." https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.displayattribute.name(v=vs.110).aspx (2认同)

Wah*_*tar 20

更新:

我知道现在为时已晚,但我想添加此更新:

我正在使用由Phil 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

    [LocalizedDisplayName("Password", typeof(Res.Model.Shared.ModelProperties))]
    public string Password { get; set; }
Run Code Online (Sandbox Code Playgroud)

有关完整的本地化教程,请参阅此页面.


Mag*_*son 11

通过选择资源属性并将"Custom Tool"切换为"PublicResXFileCodeGenerator"并将操作构建到"Embedded Resource",我让Gunders回答了我的App_GlobalResources.请观察下面的Gunders评论.

在此输入图像描述

奇迹般有效 :)


cod*_*e4j 5

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))]
}
Run Code Online (Sandbox Code Playgroud)
  1. 定义属性的ResourceType,以便查找资源
  2. 定义用于资源键的属性的名称,在C#6.0之后,您可以使用nameof强类型支持而不是硬编码键.

  3. 在控制器中设置当前线程的文化.

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

  1. 将资源的可访问性设置为public

  2. 像这样在cshtml中显示标签

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