web-dev-qa-db-ja.com

リソースのDisplayName属性?

ローカライズされたアプリケーションがあり、特定のモデルプロパティのDisplayNameをリソースから設定できるかどうか疑問に思っています。

私はこのようなことをしたいです:

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

しかし、コンパイラーが「属性引数は定数式、typeof式、または属性パラメーター型の配列作成式でなければならない」と言っているように、私はそれができません。

回避策はありますか?ラベルを手動で出力していますが、これらはバリデータの出力に必要です!

159
Palantir

カスタム属性の記述はどうですか:

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; }
}
108
Darin Dimitrov

MVC 3および.NET 4を使用している場合、System.ComponentModel.DataAnnotations名前空間で新しい Display 属性を使用できます。この属性はDisplayName属性に代わるもので、ローカライズのサポートなど、より多くの機能を提供します。

あなたの場合、次のように使用します:

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

補足として、この属性はApp_GlobalResourcesまたはApp_LocalResources内のリソースでは機能しません。これは、これらのリソースが使用するカスタムツール(GlobalResourceProxyGenerator)と関係しています。代わりに、リソースファイルが「埋め込みリソース」に設定されていることを確認し、「ResXFileCodeGenerator」カスタムツールを使用します。

(補足として、MVCでApp_GlobalResourcesまたはApp_LocalResourcesを使用するべきではありません。これがなぜなのかについて詳しく読むことができます here

367
René

リソースファイルを開いてアクセス修飾子をpublicまたはinternalに変更すると、リソースファイルからクラスが生成され、厳密に型指定されたリソース参照を作成できます。

Option for resource file code generation

つまり、代わりにこのようなことを行うことができます(C#6.0を使用)。次に、firstnameが小文字であるかラクダケースであるかを覚えておく必要はありません。また、他のプロパティが同じリソース値を使用しているかどうかを確認し、すべての参照を検索します。

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

更新:

遅すぎることはわかっていますが、このアップデートを追加したいと思います。

Phil Haacked によって提示されたConventional Model Metadata Providerを使用しています。より強力で簡単に適用できます: 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; }

完全なローカライズチュートリアルについては、 このページ を参照してください。

20
Wahid Bitar

リソースプロパティを選択し、「カスタムツール」を「PublicResXFileCodeGenerator」に切り替えて、アクションを「Embedded Resource」にビルドすることで、App_GlobalResourcesでGundersの回答を得ました。以下のガンダーズのコメントをご覧ください。

enter image description here

魅力のように動作します:)

11
Magnus Karlsson
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. リソースのキーに使用される属性のNameを定義します。C#6.0以降では、キーをハードコーディングする代わりにnameofを使用して強力な型付きサポートを行うことができます。

  3. 現在のスレッドのカルチャをコントローラーに設定します。

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

  1. リソースのアクセシビリティをパブリックに設定します

  2. ラベルをcshtmlのように表示します

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

5
code4j