来自资源的DisplayName属性?

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

我想要做这样的事情:

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

但我不能这样做,因为编译器说:“属性参数必须是一个常量expression式,typeofexpression式或数组创buildexpression式属性参数types”:(

有没有解决办法? 我手动输出标签,但我需要这些validation器输出!

如何编写自定义属性:

 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,则可以使用System.ComponentModel.DataAnnotations命名空间中的新Display属性。 该属性取代了DisplayName属性,并提供了更多的function,包括本地化支持。

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

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

作为一个方面说明,这个属性将不适用于App_GlobalResources或App_LocalResources中的资源。 这与这些资源使用的自定义工具(GlobalResourceProxyGenerator)有关。 相反,请确保您的资源文件设置为“embedded资源”,并使用“ResXFileCodeGenerator”自定义工具。

(另外一个方面,你不应该在MVC中使用App_GlobalResources或者App_LocalResources,你可以在这里阅读更多关于这种情况的信息 )

更新:

我知道这太晚了,但我想添加此更新:

我使用由Phil Haacked 提供常规模型元数据提供程序 ,它更强大,易于应用看看它: ConventionalModelMetadataProvider


老答案

在这里,如果你想支持多种types的资源:

 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; } 

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

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

资源文件代码生成选项

这意味着你可以做这样的事情(使用C#6.0)。 那么你不必记得,如果名字是lowercased或camelcased。 您可以看到其他属性是否使用相同的资源值来查找所有引用。

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

我通过select资源属性并将“定制工具”切换到“PublicResXFileCodeGenerator”并将操作构build到“embedded式资源”,让Gunders回答了我的App_GlobalResources的工作。 请注意下面的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))] } 
  1. 定义属性的ResourceType ,以便查找资源
  2. 定义用于资源键的属性的名称 ,在C#6.0之后,您可以使用nameof作为强types支持,而不是硬编码键。

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

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

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

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

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