it-swarm.com.de

DisplayName-Attribut aus Ressourcen?

Ich habe eine lokalisierte Anwendung und frage mich, ob es möglich ist, dass DisplayName für eine bestimmte Modelleigenschaft aus einer Ressource festgelegt wird.

Ich würde gerne so etwas machen:

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

Aber ich kann nicht dazu, wie der Compiler sagt: "Ein Attributargument muss ein konstanter Ausdruck, ein Ausdruck vom Typ" typeof "oder ein Ausdruck zur Array-Erstellung eines Attributparametertyps sein" :(

Gibt es Workarounds? Ich gebe Etiketten manuell aus, aber ich brauche diese für die Validator-Ausgabe!

159
Palantir

Wie wäre es, ein benutzerdefiniertes Attribut zu schreiben:

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

was so verwendet werden könnte:

public class MyModel 
{
    [Required]
    [LocalizedDisplayName("labelForName")]
    public string Name { get; set; }
}
108
Darin Dimitrov

Wenn Sie MVC 3 und .NET 4 verwenden, können Sie das neue Attribut Display im Namespace System.ComponentModel.DataAnnotations Verwenden. Dieses Attribut ersetzt das Attribut DisplayName und bietet viel mehr Funktionen, einschließlich der Unterstützung der Lokalisierung.

In Ihrem Fall würden Sie es so verwenden:

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

Nebenbei bemerkt, dieses Attribut funktioniert nicht mit Ressourcen in App_GlobalResources Oder App_LocalResources. Dies hängt mit dem benutzerdefinierten Tool (GlobalResourceProxyGenerator) zusammen, das diese Ressourcen verwenden. Stellen Sie stattdessen sicher, dass Ihre Ressourcendatei auf "Eingebettete Ressource" eingestellt ist, und verwenden Sie das benutzerdefinierte Tool "ResXFileCodeGenerator".

(Als weitere Randnotiz sollten Sie nicht App_GlobalResources Oder App_LocalResources Mit MVC verwenden. Sie können mehr darüber lesen, warum dies der Fall ist hier )

367
René

Wenn Sie Ihre Ressourcendatei öffnen und den Zugriffsmodifikator in public oder internal ändern, wird aus Ihrer Ressourcendatei eine Klasse generiert, mit der Sie stark typisierte Ressourcenverweise erstellen können.

Option for resource file code generation

Das heißt, Sie können stattdessen so etwas tun (mit C # 6.0). Dann brauchen Sie sich nicht zu erinnern, ob der Vorname in Kleinbuchstaben oder in Kamelbuchstaben geschrieben war. Sie können feststellen, ob andere Eigenschaften denselben Ressourcenwert verwenden, und alle Verweise suchen.

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

Aktualisieren:

Ich weiß, dass es zu spät ist, aber ich möchte dieses Update hinzufügen:

Ich verwende den konventionellen Modell-Metadaten-Provider , der von Phil Haacked vorgestellt wird, ist leistungsfähiger und einfacher zu bedienen bewerben schauen Sie es sich an: ConventionalModelMetadataProvider


Alte Antwort

Hier, wenn Sie viele Arten von Ressourcen unterstützen möchten:

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

Dann benutze es so:

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

Das vollständige Lernprogramm zur Lokalisierung finden Sie auf dieser Seite .

20
Wahid Bitar

Ich habe Gunders Antwort mit meiner App_GlobalResources erhalten, indem ich die Ressourceneigenschaften ausgewählt und "Custom Tool" auf "PublicResXFileCodeGenerator" und Aktion auf "Embedded Resource" gesetzt habe. Bitte beachten Sie Gunders Kommentar unten.

enter image description here

Klappt wunderbar :)

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. Definieren Sie ResourceType des Attributs, damit nach einer Ressource gesucht wird
  2. Definieren Sie Name des Attributs, das für den Schlüssel der Ressource verwendet wird. Nach C # 6.0 können Sie nameof für eine starke typisierte Unterstützung verwenden, anstatt den Schlüssel hart zu codieren.

  3. Stellen Sie die Kultur des aktuellen Threads im Controller ein.

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

  1. Stellen Sie die Zugänglichkeit der Ressource auf öffentlich ein

  2. Zeigen Sie die Beschriftung in cshtml wie folgt an

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

5
code4j