Kaynaklardan DisplayName özelliği?


160

Yerelleştirilmiş bir uygulama var ve ben DisplayNamebir kaynak belirli bir model özelliği için ayarlanmış olup olmadığını merak ediyorum .

Böyle bir şey yapmak istiyorum:

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

Ancak derleyenin dediği gibi yapamam: "Bir özellik bağımsız değişkeni, bir özellik parametre türünün sabit bir ifadesi, typeof ifadesi veya dizi oluşturma ifadesi olmalıdır" :(

Herhangi bir geçici çözüm var mı? Etiketleri elle çıktı alıyorum, ancak validator çıkışı için bunlara ihtiyacım var!

Yanıtlar:


112

Özel bir özellik yazmaya ne dersiniz:

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

Bu şekilde kullanılabilir:

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

Evet, bu sabah benzer bir çözüm üzerinde çalıştım ve bu mümkün. Sonra aynı yaklaşıma sahip olan bu gönderiyi buldum
Palantir

23
@ Gönderi, bunun altında, (en çok oyu ile), çok daha hoş bir çözümdür. Sadece Kabul Edilen mesajları okuyan insanlar için
321X

1
Bu aslında tüm çeviriler için aynı değeri döndürecek çünkü farklı çevirilere erişmek için işe yaramaz. Kaynak değişkenini yerel bir değişkende depolayın ve bunun yerine DisplayName'i geçersiz kılın
Fischer

5
YAPILACAKLAR için öneri: Return Resources.Language.ResourceManager.GetString (resourceId);
Leonel Sanches da Silva

4
Sen kullanmalıdır: [Display (Ad = "labelForName", KaynakTürü = typeof (Resources.Resources))] olarak ... aşağıda tarif
Frank Boucher

376

MVC 3 ve .NET 4 kullanıyorsanız Display, System.ComponentModel.DataAnnotationsad alanında yeni özniteliği kullanabilirsiniz . Bu özellik, özelliğin yerini alır DisplayNameve yerelleştirme desteği de dahil olmak üzere çok daha fazla işlevsellik sağlar.

Sizin durumunuzda şu şekilde kullanabilirsiniz:

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

Bir yan not olarak, bu özellik App_GlobalResourcesveya içindeki kaynaklarla çalışmaz App_LocalResources. Bu, GlobalResourceProxyGeneratorbu kaynakların kullandığı özel araçla ( ) ilgilidir. Bunun yerine kaynak dosyanızın 'Gömülü kaynak' olarak ayarlandığından emin olun ve 'ResXFileCodeGenerator' özel aracını kullanın.

(Başka bir yan not olarak, MVC ile App_GlobalResourcesveya App_LocalResourcesMVC kullanmamalısınız. Bunun neden böyle olduğu hakkında daha fazla bilgiyi buradan edinebilirsiniz )


Bu, burada kullanılan belirli örnek için iyidir, ancak dize isteyen dinamik özellik ayarlayıcılarının çoğunda işe yaramaz.
kingdango

1
Üretime geçmeden önce tüm yerel ayarlarımıza sahip olduğumuzda bu iyidir. Ama db dizeleri için db çağırmak istiyorsanız, o zaman bu tür bir yaklaşım uygun değildir. Ayrıca kaynak dosyasının dezavantajı, değişiklikleri etkilemek için tekrar derleme gerektirmesidir, yani istemciye başka bir sürüm yayınlamanız gerekir. Bunu kötü bir yaklaşım olarak söylemiyorum, lütfen böyle hissetmeyin
kbvishnu

Sadece bir sorun: Modeldeki kaynak türünü bilmeliyiz. İki farklı projede bir model DLL ve bir web sitem var. Modelde görünen adları ve web sitesinde kaynak türünü belirleyebilmek istiyorum ...
Kek

1
Resharper'ı alın ve projenizde kaynak dosyasını oluşturun; otomatik olarak hatırlatıp Ad'ı kaynak dosyasına taşımanıza yardımcı olur.
anIBMer

14
C # 6 ile bunun yerine Name = "labelForName"kullanabilirsiniz Name = nameof(Resources.Resources.labelForName).
Uwe Keim

35

Kaynak dosyanızı açar ve erişim değiştiricisini genel veya dâhili olarak değiştirirseniz, kaynak dosyanızdan güçlü yazılan kaynak başvuruları oluşturmanıza olanak tanıyan bir sınıf oluşturulur.

Kaynak dosya kodu oluşturma seçeneği

Bu, bunun gibi bir şey yapabileceğiniz anlamına gelir (C # 6.0 kullanarak). O zaman adın küçük harflerle mi yoksa deveyle mi yazılmış olduğunu hatırlamanız gerekmez. Diğer özelliklerin tüm başvuruları bulmakla aynı kaynak değerini kullanıp kullanmadığını görebilirsiniz.

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

bu Winforms ile çalışacak mı? Ben kaynaklardan ek açıklama görüntüle ekledi bir sınıf var ve ben özellik adını almak için bağlantı GetAttributeFrom yöntemi kullanılır ama yerelleştirilmiş bir göstermez!
Dark_Knight

2
Yerelleştirilmiş metni almak için attribute.Name veya attribute.GetName () kullanıyor musunuz? .Name belgeleri "Name özelliğinin değerini almak için bu özelliği kullanmayın. Bunun yerine GetName yöntemini kullanın." msdn.microsoft.com/en-us/library/…
Tikall

Evet, GetName () kullanmak zorunda olduğunu anladım. Teşekkürler
Dark_Knight

20

Güncelleme:

Çok geç olduğunu biliyorum ama bu güncellemeyi eklemek istiyorum:

Phil Haacked tarafından sunulan Konvansiyonel Model Meta Veri Sağlayıcısını kullanıyorum, daha güçlü ve uygulaması kolay bir göz atın: ConventionalModelMetadataProvider


Eski Cevap

Birçok türde kaynağı desteklemek istiyorsanız:

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

Sonra şu şekilde kullanın:

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

Tam yerelleştirme eğitimi için bu sayfaya bakın .


1
+1. Haack'in çözümü kesinlikle buradaki diğer çözümlerle karşılaştırıldığında en zarif çözümdür. ASP.NET MVC'deki kural tabanlı programlama stiline çok iyi uyum sağlar ve Global.asax.cs içindeki tek bir nuget komutu ve tek bir kod satırı ile kolayca uygulanır.
Nilzor

11

Gunders yanıtı kaynak özelliklerini seçerek ve "Özel Aracı" "PublicResXFileCodeGenerator" ve "Gömülü Kaynak" için eylem inşa ederek App_GlobalResources ile çalışma cevap aldım. Lütfen aşağıdaki Gunders yorumuna göz atın.

resim açıklamasını buraya girin

Tıkır tıkır çalışıyor :)


Bu, tıpkı App_GlobalResources dışında bir kaynak dosyası eklediğiniz gibi derlenecek bir kaynak dosyasına neden olur. Bu nedenle kaynak dosyanız artık kesinlikle iyi olan "App_GlobalResources" kaynak dosyası gibi davranmayacak. Ama bunun farkında olmalısınız. Yani artık kaynak dosyasını App_GlobalResources içine koymanın "faydalarına" sahip değilsiniz. Siz de başka bir yere koyabilirsiniz.
René

5
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. Özkaynağın bir Kaynağı araması için ResourceType değerini tanımlama
  2. Define Adı C # 6.0 sonra kullanabileceğiniz, kaynağın anahtarı için kullanılan özelliğin nameofanahtarını kodlama güçlü yazılan desteği yerine sert için.

  3. Denetleyicide geçerli iplik kültürünü ayarlayın.

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

  1. Kaynağın erişilebilirliğini herkese açık olarak ayarlama

  2. Etiketi Display cshtml böyle

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.