Saya ingin tahu apakah mungkin untuk mendapatkan atribut dari enum
nilai dan bukan dari nilai enum
itu sendiri? Sebagai contoh, misalkan saya memiliki yang berikut ini enum
:
using System.ComponentModel; // for DescriptionAttribute
enum FunkyAttributesEnum
{
[Description("Name With Spaces1")]
NameWithoutSpaces1,
[Description("Name With Spaces2")]
NameWithoutSpaces2
}
Apa yang saya inginkan adalah tipe enum, menghasilkan 2-tuple nilai string enum dan deskripsinya.
Nilai itu mudah:
Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum));
foreach (int value in values)
Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value);
Tapi bagaimana cara mendapatkan nilai atribut deskripsi, untuk mengisi Tuple.Desc
? Saya bisa memikirkan bagaimana melakukannya jika atribut milik enum
itu sendiri, tetapi saya bingung bagaimana cara mendapatkannya dari nilai enum
.
c#
reflection
enums
.net-attributes
Alex K
sumber
sumber
DescriptionAttribute
.Jawaban:
Ini harus melakukan apa yang Anda butuhkan.
sumber
Sepotong kode ini akan memberi Anda metode ekstensi kecil yang bagus pada enum apa pun yang memungkinkan Anda mengambil atribut generik. Saya percaya ini berbeda dengan fungsi lambda di atas karena lebih mudah digunakan dan sedikit - Anda hanya perlu memasukkan tipe generik.
sumber
IndexOutOfRangeException
?GetCustomAttributes()
lalu mendapatkan elemen pertama alih-alih meneleponGetCustomAttribute()
?Ini adalah implementasi generik menggunakan lambda untuk seleksi
Sebut saja seperti ini:
sumber
FlagsAttribute
). Dalam hal ini,enumeration.GetType().GetMember(enumeration.ToString())[0]
akan gagal.value.GetType().GetField(value.ToString()).GetCustomAttributes(false).OfType<T>().SingleOrDefault()
tetapi harus mengakui cara eksplisit Anda lebih baik.Saya telah menggabungkan beberapa jawaban di sini untuk membuat solusi yang lebih fleksibel. Saya menyediakannya untuk berjaga-jaga jika itu bermanfaat bagi orang lain di masa depan. Posting asli di sini .
Solusi ini menciptakan sepasang metode ekstensi pada Enum. Yang pertama memungkinkan Anda menggunakan refleksi untuk mengambil atribut apa pun yang terkait dengan nilai Anda. Panggilan kedua secara khusus mengambil
DescriptionAttribute
dan mengembalikanDescription
nilainya.Sebagai contoh, pertimbangkan untuk menggunakan
DescriptionAttribute
atribut dariSystem.ComponentModel
Untuk menggunakan metode ekstensi di atas, sekarang Anda cukup memanggil yang berikut:
atau
sumber
Selain tanggapan AdamCrawford , saya telah membuat metode penyuluhan yang lebih khusus yang memberikannya untuk mendapatkan deskripsi.
karenanya, untuk mendapatkan deskripsi, Anda bisa menggunakan metode ekstensi asli sebagai
atau Anda cukup memanggil metode ekstensi di sini sebagai:
Yang diharapkan semoga membuat kode Anda sedikit lebih mudah dibaca.
sumber
Lancar satu liner ...
Di sini saya menggunakan
DisplayAttribute
yang berisi propertiName
danDescription
.Contoh
Keluaran
sumber
Berikut ini kode untuk mendapatkan informasi dari atribut Display. Ini menggunakan metode generik untuk mengambil atribut. Jika atribut tidak ditemukan, itu mengubah nilai enum ke string dengan case pascal / unta dikonversi ke case title (kode diperoleh di sini )
Dan ini adalah metode ekstensi untuk string untuk mengkonversi ke judul kasus:
sumber
Saya menerapkan metode ekstensi ini untuk mendapatkan deskripsi dari nilai enum. Ini bekerja untuk semua jenis enum.
sumber
Dapatkan kamus dari enum.
Sekarang panggil ini seperti ...
Metode EnumDecription Ext
sumber
Inilah versi .NET Core dari jawaban AdamCrawford, menggunakan System.Reflection.TypeExtensions ;
sumber
Menambahkan solusi saya untuk Net Framework dan NetCore.
Saya menggunakan ini untuk implementasi Net Framework saya:
Ini tidak berfungsi untuk NetCore jadi saya memodifikasinya untuk melakukan ini:
Contoh Pencacahan:
Contoh Penggunaan untuk statis ditambahkan:
sumber
Dengan memanfaatkan beberapa fitur bahasa C # yang lebih baru, Anda dapat mengurangi jumlah baris:
sumber
Saya jawaban ini untuk menyiapkan kotak kombo dari atribut enum yang hebat.
Saya kemudian perlu kode kebalikan sehingga saya bisa mendapatkan pilihan dari kotak dan mengembalikan enum dalam jenis yang benar.
Saya juga memodifikasi kode untuk menangani kasus di mana atribut hilang
Untuk manfaat orang berikutnya, inilah solusi terakhir saya
}
sumber
Jika Anda
enum
mengandung nilai sepertiEquals
Anda mungkin menabrak beberapa bug menggunakan beberapa ekstensi dalam banyak jawaban di sini. Ini karena biasanya diasumsikan bahwatypeof(YourEnum).GetMember(YourEnum.Value)
hanya akan mengembalikan satu nilai, yang merupakan nilaiMemberInfo
Andaenum
. Inilah jawaban versi Adam Crawford yang sedikit lebih aman .sumber
Metode ekstensi ini akan mendapatkan representasi string dari nilai enum menggunakan XmlEnumAttribute-nya. Jika tidak ada XmlEnumAttribute, itu kembali ke enum.ToString ().
sumber
Dan jika Anda ingin daftar nama lengkap, Anda dapat melakukan sesuatu seperti
sumber
Guys jika membantu saya akan berbagi dengan Anda solusi saya: Definisi atribut Kustom:
Sekarang karena saya membutuhkannya di dalam definisi HtmlHelper tentang Ekstensi HtmlHelper:
Semoga ini bisa membantu
sumber
Sekarang akan menghasilkan kesalahan dalam kasus ini 1 "Setara"
jadi jika itu sama mengembalikan nama enum daripada nama tampilan karena enumMember.GetCustomAttribute () mendapat null jika tampilanname dan nama enum sama .....
sumber
Atau, Anda dapat melakukan hal berikut:
sumber
Ini adalah bagaimana saya menyelesaikannya tanpa menggunakan bantuan kustom atau ekstensi dengan .NET core 3.1.
Kelas
Pisau cukur
sumber
Masalah kinerja
Jika Anda ingin kinerja yang lebih baik, inilah cara yang harus dilakukan:
Mengapa ini memiliki kinerja yang lebih baik?
Karena metode bawaan semua menggunakan kode yang sangat mirip dengan ini kecuali mereka juga menjalankan banyak kode lain yang tidak kami pedulikan . Kode Enum C # cukup mengerikan pada umumnya.
Kode di atas telah Linq-ified dan efisien sehingga hanya berisi bit yang kita pedulikan.
Mengapa kode bawaan lambat?
Pertama tentang Enum.ToString () -vs- Enum.GetName (..)
Selalu gunakan yang terakhir. (Atau lebih baik lagi, seperti yang akan menjadi jelas di bawah ini.)
ToString () menggunakan yang terakhir secara internal, tetapi sekali lagi, juga melakukan banyak hal lain yang tidak kita inginkan, misalnya mencoba untuk menggabungkan bendera, mencetak angka dll. Kami hanya tertarik pada konstanta yang didefinisikan di dalam enum.
Enum.GetName mendapatkan semua bidang, membuat array string untuk semua nama, menggunakan ToUInt64 di atas pada semua RawConstantValues mereka untuk membuat array UInt64 dari semua nilai, mengurutkan kedua array berdasarkan nilai UInt64, dan akhirnya mendapatkan nama dari array nama dengan melakukan BinarySearch di array UInt64 untuk menemukan indeks nilai yang kita inginkan.
... dan kemudian kita membuang bidang dan array yang disortir pergi menggunakan nama itu untuk menemukan bidang lagi.
Satu kata: "Ugh!"
sumber
Atau, Anda dapat melakukan hal berikut:
Dan dapatkan deskripsi dengan yang berikut ini:
Menurut pendapat saya ini adalah cara yang lebih efisien untuk melakukan apa yang ingin Anda capai, karena tidak diperlukan refleksi ..
sumber
Anda juga dapat menentukan nilai enum seperti
Name_Without_Spaces
, dan saat Anda menginginkan deskripsi digunakanName_Without_Spaces.ToString().Replace('_', ' ')
untuk mengganti garis bawah dengan spasi.sumber