来自资源的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))] }
- 定义属性的ResourceType ,以便查找资源
-
定义用于资源键的属性的名称 ,在C#6.0之后,您可以使用
nameof
作为强types支持,而不是硬编码键。 -
在控制器中设置当前线程的文化。
Resource.Culture = CultureInfo.GetCultureInfo("zh-CN");
-
将资源的可访问性设置为公共
-
像这样在cshtml中显示标签
@Html.DisplayNameFor(model => model.Age)