Saya mencari cara untuk melokalkan nama properti yang ditampilkan di PropertyGrid. Nama properti mungkin "diganti" menggunakan atribut DisplayNameAttribute. Sayangnya atribut tidak boleh memiliki ekspresi non konstan. Jadi saya tidak dapat menggunakan sumber daya yang diketik dengan kuat seperti:
class Foo
{
[DisplayAttribute(Resources.MyPropertyNameLocalized)] // do not compile
string MyProperty {get; set;}
}
Saya telah melihat-lihat dan menemukan beberapa saran untuk mewarisi dari DisplayNameAttribute agar dapat menggunakan sumber daya. Saya akan berakhir dengan kode seperti:
class Foo
{
[MyLocalizedDisplayAttribute("MyPropertyNameLocalized")] // not strongly typed
string MyProperty {get; set;}
}
Namun saya kehilangan manfaat sumber daya yang diketik dengan kuat yang jelas bukan hal yang baik. Kemudian saya menemukan DisplayNameResourceAttribute yang mungkin saya cari. Tapi itu seharusnya di namespace Microsoft.VisualStudio.Modeling.Design dan saya tidak dapat menemukan referensi apa yang harus saya tambahkan untuk namespace ini.
Ada yang tahu jika ada cara yang lebih mudah untuk mencapai pelokalan DisplayName dengan cara yang baik? atau jika ada cara untuk menggunakan apa yang tampaknya digunakan Microsoft untuk Visual Studio?
sumber
Jawaban:
Ada atribut Tampilan dari System.ComponentModel.DataAnnotations di .NET 4. Ia bekerja pada MVC 3
PropertyGrid
.Ini mencari sumber daya yang bernama
UserName
dalamMyResources
file .resx Anda .sumber
typeof(MyResources)
, Anda mungkin perlu menyetel pengubah akses file sumber daya Anda ke Publik .Kami melakukan ini untuk sejumlah atribut untuk mendukung banyak bahasa. Kami telah mengambil pendekatan yang mirip dengan Microsoft, di mana mereka mengganti atribut dasarnya dan meneruskan nama sumber daya daripada string sebenarnya. Nama sumber daya kemudian digunakan untuk melakukan pencarian di sumber daya DLL untuk mengembalikan string sebenarnya.
Sebagai contoh:
Anda dapat mengambil langkah ini lebih jauh ketika benar-benar menggunakan atribut tersebut, dan menetapkan nama sumber daya Anda sebagai konstanta di kelas statis. Dengan begitu, Anda mendapatkan deklarasi seperti.
Pembaruan
ResourceStrings
akan terlihat seperti (catatan, setiap string akan merujuk ke nama sumber daya yang menentukan string sebenarnya):sumber
[MyNamespace].[MyResourceFile].ResourceManager.GetString("MyString");
Berikut adalah solusi yang saya dapatkan dalam perakitan terpisah (disebut "Umum" dalam kasus saya):
dengan kode untuk mencari sumber daya:
Penggunaan tipikal adalah:
Apa yang cukup jelek karena saya menggunakan string literal untuk kunci sumber daya. Menggunakan konstanta berarti memodifikasi Resources.Designer.cs yang mungkin bukan ide yang bagus.
Kesimpulan: Saya tidak senang dengan itu, tetapi saya bahkan kurang senang dengan Microsoft yang tidak dapat memberikan sesuatu yang berguna untuk tugas umum seperti itu.
sumber
ResourceManager
properti. Alih-alih, Anda bisa langsung mendapatkan properti dari jenis yang disediakan di parameter:PropertyInfo property = resourceManagerProvider.GetProperty(resourceKey, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
Menggunakan atribut Display (dari System.ComponentModel.DataAnnotations) dan ekspresi nameof () di C # 6, Anda akan mendapatkan solusi yang dilokalkan dan diketik dengan kuat.
sumber
Anda bisa menggunakan T4 untuk menghasilkan konstanta. Saya menulis satu:
sumber
Ini adalah pertanyaan lama, tapi menurut saya ini adalah masalah yang sangat umum, dan inilah solusi saya di MVC 3.
Pertama, template T4 diperlukan untuk menghasilkan konstanta untuk menghindari string yang tidak menyenangkan. Kami memiliki file sumber daya 'Labels.resx' menampung semua string label. Oleh karena itu, templat T4 menggunakan file sumber daya secara langsung,
Kemudian, metode ekstensi dibuat untuk melokalkan 'DisplayName',
Atribut 'DisplayName' diganti dengan atribut 'DisplayLabel' untuk membaca dari 'Labels.resx' secara otomatis,
Setelah semua pekerjaan persiapan itu, saatnya menyentuh atribut validasi default tersebut. Saya menggunakan atribut 'Wajib' sebagai contoh,
Sekarang, Kita dapat menerapkan atribut tersebut dalam model kita,
Secara default, nama properti digunakan sebagai kunci untuk mencari 'Label.resx', tetapi jika Anda menyetelnya melalui 'DisplayLabel', ia akan menggunakannya.
sumber
Anda dapat membuat subkelas DisplayNameAttribute untuk menyediakan i18n, dengan mengganti salah satu metode. Seperti itu. edit: Anda mungkin harus puas menggunakan konstanta untuk kunci.
sumber
Saya menggunakan cara ini untuk memecahkan kasus saya
Dengan kode
sumber
Nah, perakitannya
Microsoft.VisualStudio.Modeling.Sdk.dll
. yang disertakan dengan Visual Studio SDK (With Visual Studio Integration Package).Tapi itu akan digunakan dengan cara yang hampir sama seperti atribut Anda; tidak ada cara untuk menggunakan resource tipe kuat dalam atribut hanya karena atribut tidak konstan.
sumber
Saya minta maaf untuk kode VB.NET, C # saya agak berkarat ... Tapi Anda akan mengerti, bukan?
Pertama-tama, buat kelas baru
LocalizedPropertyDescriptor
:, yang mewarisiPropertyDescriptor
. GantiDisplayName
properti seperti ini:Some.ResourceManager
adalah ResourceManager dari file resource yang berisi terjemahan Anda.Selanjutnya, implementasikan
ICustomTypeDescriptor
di kelas dengan properti yang dilokalkan, dan gantiGetProperties
metode:Anda sekarang dapat menggunakan atribut 'DisplayName` untuk menyimpan referensi ke nilai dalam file sumber daya ...
prop_description
adalah kunci dalam file sumber daya.sumber