C# 资源中的DisplayName属性?

C# 资源中的DisplayName属性?,c#,asp.net-mvc,localization,resources,resx,C#,Asp.net Mvc,Localization,Resources,Resx,我有一个本地化的应用程序,我想知道是否可以从资源中为某个模型属性设置DisplayName 我想这样做: public class MyModel { [Required] [DisplayName(Resources.Resources.labelForName)] public string name{ get; set; } } public class MyModel { [Required] [LocalizedDisplayName("labelFor

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

我想这样做:

public class MyModel {
  [Required]
  [DisplayName(Resources.Resources.labelForName)]
  public string name{ get; set; }
}
public class MyModel 
{
    [Required]
    [LocalizedDisplayName("labelForName")]
    public string Name { get; set; }
}
    [LocalizedDisplayName("Password", typeof(Res.Model.Shared.ModelProperties))]
    public string Password { get; set; }
public class MyModel
{
    [Required]
    [Display(Name = "labelForName", ResourceType = typeof(Resources.Resources))]
    public string name{ get; set; }
}
但我不能这样做,正如编译器所说:“属性参数必须是常量表达式、typeof表达式或属性参数类型的数组创建表达式”:(


有什么解决方法吗?我正在手动输出标签,但我需要这些标签用于验证程序输出!

如何编写自定义属性:

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]
  [DisplayName(Resources.Resources.labelForName)]
  public string name{ get; set; }
}
public class MyModel 
{
    [Required]
    [LocalizedDisplayName("labelForName")]
    public string Name { get; set; }
}
    [LocalizedDisplayName("Password", typeof(Res.Model.Shared.ModelProperties))]
    public string Password { get; set; }
public class MyModel
{
    [Required]
    [Display(Name = "labelForName", ResourceType = typeof(Resources.Resources))]
    public string name{ get; set; }
}
更新: 我知道为时已晚,但我想添加此更新:

我使用的是传统的模型元数据提供程序,它的功能更强大,也更易于应用。请看:


旧答案 如果您想支持多种类型的资源,请点击此处:

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);
        }
    }
}
然后像这样使用它:

public class MyModel {
  [Required]
  [DisplayName(Resources.Resources.labelForName)]
  public string name{ get; set; }
}
public class MyModel 
{
    [Required]
    [LocalizedDisplayName("labelForName")]
    public string Name { get; set; }
}
    [LocalizedDisplayName("Password", typeof(Res.Model.Shared.ModelProperties))]
    public string Password { get; set; }
public class MyModel
{
    [Required]
    [Display(Name = "labelForName", ResourceType = typeof(Resources.Resources))]
    public string name{ get; set; }
}

有关完整的本地化教程,请参见。

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

在您的情况下,您可以这样使用它:

public class MyModel {
  [Required]
  [DisplayName(Resources.Resources.labelForName)]
  public string name{ get; set; }
}
public class MyModel 
{
    [Required]
    [LocalizedDisplayName("labelForName")]
    public string Name { get; set; }
}
    [LocalizedDisplayName("Password", typeof(Res.Model.Shared.ModelProperties))]
    public string Password { get; set; }
public class MyModel
{
    [Required]
    [Display(Name = "labelForName", ResourceType = typeof(Resources.Resources))]
    public string name{ get; set; }
}
请注意,此属性不适用于
App\u GlobalResources
App\u LocalResources
中的资源。这与自定义工具(
GlobalResourceProxyGenerator
)有关这些资源使用。请确保您的资源文件设置为“嵌入式资源”,并使用“ResXFileCodeGenerator”自定义工具


(作为进一步的补充说明,您不应该将
App\u GlobalResources
App\u LocalResources
与MVC一起使用。您可以阅读更多关于为什么会出现这种情况的信息)

通过选择资源属性并将“自定义工具”切换到“PublicResXFileCodeGenerator”,我得到了Gunders使用我的App\u GlobalResources的答案并构建“嵌入式资源”的操作。 请注意下面的冈德斯评论


工作原理类似于一个符咒:)

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

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

这意味着你可以做类似的事情(使用C#6.0)。 那么你就不必记得名字是小写还是大写了。您可以查看其他属性是否使用相同的资源值和“查找所有引用”

[Display(Name = nameof(PropertyNames.FirstName), ResourceType = typeof(PropertyNames))]
public string FirstName { get; set; }
  • 定义属性的ResourceType,以便它查找资源
  • 定义用于资源键的属性的Name,在C#6.0之后,您可以使用
    nameof
    实现强类型支持,而不是硬编码键

  • 在控制器中设置当前线程的区域性

  • Resource.Culture=CultureInfo.GetCultureInfo(“zh CN”)

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

  • cshtml中显示标签,如下所示


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

    是的,我今天早上研究了一个类似的解决方案,它是可行的。然后我发现这个帖子也有同样的方法:@Gunder他的帖子,在这个帖子下面(得票最多),是一个更好的解决方案。仅仅对于那些只阅读已接受帖子的人来说,这实际上并不适用于访问不同的翻译,因为它将为所有用户返回相同的值,不管是什么。将resourceid存储在局部变量中,并覆盖DisplayName而不是TODO的建议:返回Resources.Language.ResourceManager.GetString(resourceid);您应该使用:[Display(Name=“labelForName”,ResourceType=typeof(Resources.Resources))]如下所述……这对于这里使用的特定示例很好,但对于大多数需要字符串的动态属性设置程序来说,它不起作用。在部署到生产环境之前,当我们拥有所有的区域设置时,这很好。但是,如果我想为db字符串调用db,那么这种方法是不合适的。资源文件的另一个缺点是,它需要再次编译以实现更改,这意味着您需要向客户端发布另一个版本。我并不是说这是一个糟糕的方法,请不要觉得这只是一个问题:我们必须知道模型中的资源类型。我在两个不同的项目中有一个模型DLL和一个网站。我希望能够在模型中设置显示名称并在网站中设置资源类型…获取Resharper,并在项目中创建资源文件,它将自动提醒并帮助您将名称移动到资源文件中。使用C#6,而不是
    Name=“labelForName”
    您还可以使用
    Name=nameof(Resources.Resources.labelForName)
    。这将导致编译一个资源文件,就像您在App_GlobalResources之外添加了一个资源文件一样。因此,您的资源文件将不再作为“App_GlobalResources”资源文件运行,这是绝对正确的。但您应该知道它。因此,您不再具有“好处"把资源文件放到App_GlobalResources中。你也可以把它放到别的地方。+1.与这里的其他解决方案相比,Haack的解决方案无疑是最优雅的。它非常适合ASP.NET MVC中基于约定的编程风格,并且很容易通过一个nuget命令和一行o来实现Global.asax.cs中的f代码。这是否适用于Winforms?我有一个类,我从参考资料中添加了显示注释,并从中使用GetAttributeFrom方法获取属性名称,但它没有显示本地化的属性名称!您是使用attribute.name还是attribute.GetName()获取本地化文本?name的文档说明“不要使用此属性获取Name属性的值。请改用GetName方法。”是的,我发现我必须