Ada sekelompok metode pribadi di kelas saya, dan saya perlu memanggil satu secara dinamis berdasarkan nilai input. Baik kode pemanggilan dan metode target dalam contoh yang sama. Kode ini terlihat seperti ini:
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType);
dynMethod.Invoke(this, new object[] { methodParams });
Dalam hal ini, GetMethod()
tidak akan mengembalikan metode pribadi. Apa BindingFlags
yang saya butuhkan untuk memasok GetMethod()
sehingga dapat menemukan metode pribadi?
c#
.net
reflection
private-methods
Jeromy Irvine
sumber
sumber
BindingFlags.NonPublic
tidak mengembalikanprivate
metode .. :(BindingFlags.Instance
jugaBindingFlags.NonPublic
untuk metode non-statis.non-static
danprivate
dan kelas diwarisi dariSystem.Web.UI.Page
.. itu membuat saya bodoh juga .. saya tidak menemukan alasan .. :(BindingFlags.FlattenHierarchy
akan memungkinkan Anda untuk mendapatkan metode dari kelas induk ke instance Anda.BindingFlags.NonPublic
tidak akan mengembalikan hasil apa pun dengan sendirinya. Ternyata, menggabungkannya denganBindingFlags.Instance
melakukan trik.sumber
internal
fungsi jugaDan jika Anda benar - benar ingin mendapatkan masalah, buat lebih mudah untuk dieksekusi dengan menulis metode ekstensi:
Dan penggunaan:
sumber
Microsoft baru-baru ini memodifikasi API refleksi yang membuat sebagian besar jawaban ini usang. Yang berikut ini harus bekerja pada platform modern (termasuk Xamarin.Forms dan UWP):
Atau sebagai metode ekstensi:
catatan:
Jika metode yang diinginkan dalam superclass dari
obj
yangT
generik harus secara eksplisit diatur dengan jenis superclass.Jika metode ini asinkron, Anda dapat menggunakan
await (Task) obj.InvokeMethod(…)
.sumber
GetDeclareMethod()
dimaksudkan untuk digunakan hanya untuk mengambil metode publik.Apakah Anda benar-benar yakin ini tidak dapat dilakukan melalui warisan? Refleksi adalah hal terakhir yang harus Anda perhatikan ketika menyelesaikan masalah, itu membuat refactoring, memahami kode Anda, dan setiap analisis otomatis lebih sulit.
Sepertinya Anda seharusnya hanya memiliki kelas DrawItem1, DrawItem2, dll yang menggantikan dynMethod Anda.
sumber
Refleksi terutama pada anggota pribadi adalah salah
Refleksi anggota pribadi melanggar prinsip enkapsulasi dan dengan demikian mengekspos kode Anda sebagai berikut:
Bagaimana jika saya tetap harus melakukannya?
Ada beberapa kasus, ketika Anda bergantung pada pihak ketiga atau Anda perlu beberapa api tidak terbuka, Anda harus melakukan beberapa refleksi. Beberapa juga menggunakannya untuk menguji beberapa kelas yang mereka miliki tetapi mereka tidak ingin mengubah antarmuka untuk memberikan akses ke anggota dalam hanya untuk tes.
Jika Anda melakukannya, lakukan dengan benar
Untuk memitigasi masalah yang mudah pecah, yang terbaik adalah mendeteksi potensi jeda dengan menguji dalam unit test yang akan berjalan dalam bentuk integrasi berkelanjutan atau semacamnya. Tentu saja, itu berarti Anda selalu menggunakan majelis yang sama (yang berisi anggota pribadi). Jika Anda menggunakan beban dinamis dan refleksi, Anda suka bermain dengan api, tetapi Anda selalu dapat menangkap Pengecualian bahwa panggilan dapat menghasilkan.
Dalam versi terbaru dari .Net Framework, CreateDelegate dikalahkan oleh faktor 50 yang dipanggil MethodInfo:
draw
panggilan akan menjadi sekitar 50x lebih cepat daripadaMethodInfo.Invoke
digunakandraw
sebagai standarFunc
seperti itu:Periksa pos saya ini untuk melihat patokan pada pemanggilan metode yang berbeda
sumber
Tidak bisakah Anda hanya memiliki metode Draw yang berbeda untuk setiap jenis yang ingin Anda Draw? Kemudian panggil metode Draw yang kelebihan beban lewat objek tipe itemType yang akan ditarik.
Pertanyaan Anda tidak memperjelas apakah itemType benar-benar merujuk ke objek dari tipe yang berbeda.
sumber
Saya pikir Anda dapat lulus di
BindingFlags.NonPublic
mana itu adalahGetMethod
metode.sumber
Meminta metode apa pun meskipun tingkat perlindungannya pada objek instance. Nikmati!
sumber
Baca jawaban (tambahan) ini (yang terkadang merupakan jawaban) untuk memahami ke mana arah ini dan mengapa beberapa orang di utas ini mengeluh bahwa "masih belum berfungsi"
Saya menulis kode yang persis sama dengan salah satu jawaban di sini . Tapi saya masih punya masalah. Saya menempatkan break point
Itu dieksekusi tetapi
mi == null
Dan itu melanjutkan perilaku seperti ini sampai saya "membangun kembali" pada semua proyek yang terlibat. Saya menguji unit satu majelis sedangkan metode refleksi duduk di majelis ketiga. Itu benar-benar membingungkan tetapi saya menggunakan Window Segera untuk menemukan metode dan saya menemukan bahwa metode pribadi saya mencoba unit test memiliki nama lama (saya menamainya). Ini memberi tahu saya bahwa perakitan lama atau PDB masih ada di sana bahkan jika proyek unit test dibangun - untuk beberapa alasan proyek itu tes tidak dibangun. "membangun kembali" bekerja
sumber
BindingFlags.NonPublic
sumber