Menggunakan refleksi, bagaimana saya bisa mendapatkan semua jenis yang mengimplementasikan antarmuka dengan C # 3.0 / .NET 3.5 dengan kode paling sedikit, dan meminimalkan iterasi?
Inilah yang ingin saya tulis ulang:
foreach (Type t in this.GetType().Assembly.GetTypes())
if (t is IMyInterface)
; //do stuff
Jawaban:
Milik saya ini di c # 3.0 :)
Pada dasarnya, jumlah iterasi paling sedikit akan selalu:
sumber
.Where(p => type.IsAssignableFrom(p) && !p.IsInterface);
untuk memfilternya (ataup.IsClass
).List<string>
tidak menerapkanIEnumerable<object>
tetapi metode ini akan mengembalikan true di. Net 4.0 karena kovarian yang memang salah. Jawaban yang benar ada di sini.Where(p => type.IsAssignableFrom(p) && p.IsClass && !p.IsAbstract
Ini berhasil untuk saya. Itu loop meskipun kelas dan memeriksa untuk melihat apakah mereka berasal dari myInterface
sumber
Untuk menemukan semua tipe dalam majelis yang mengimplementasikan antarmuka IFoo:
Perhatikan bahwa saran Ryan Rinaldi salah. Ini akan mengembalikan 0 jenis. Anda tidak dapat menulis
karena type adalah instance System.Type, dan tidak akan pernah bertipe IFoo. Sebagai gantinya, Anda memeriksa untuk melihat apakah IFoo dapat ditentukan dari jenisnya. Itu akan mendapatkan hasil yang Anda harapkan.
Juga, saran Adam Wright, yang saat ini ditandai sebagai jawabannya, juga tidak benar, dan karena alasan yang sama. Saat runtime, Anda akan melihat 0 jenis kembali, karena semua instans System.Type bukan implementor IFoo.
sumber
Saya menghargai ini adalah pertanyaan yang sangat lama tapi saya pikir saya akan menambahkan jawaban lain untuk pengguna di masa depan karena semua jawaban sampai saat ini menggunakan beberapa bentuk
Assembly.GetTypes
.Sementara GetTypes () memang akan mengembalikan semua jenis, itu tidak berarti Anda bisa mengaktifkannya dan dengan demikian berpotensi membuang a
ReflectionTypeLoadException
.Contoh klasik untuk tidak dapat mengaktifkan suatu tipe adalah ketika tipe yang dikembalikan adalah
derived
daribase
tetapibase
didefinisikan dalam rakitan yang berbeda dariderived
, rakitan yang tidak dirujuk oleh rakitan pemanggil.Jadi katakan kita memiliki:
Jika di
ClassC
dalamnya adaAssemblyC
maka kita melakukan sesuatu sesuai jawaban yang diterima:Maka itu akan melempar
ReflectionTypeLoadException
.Ini karena tanpa referensi ke
AssemblyA
dalamAssemblyC
Anda tidak akan dapat:Dengan kata lain
ClassB
tidak dapat dimuat yang merupakan sesuatu yang dipanggil dan dilemparkan oleh panggilan untuk GetTypes.Jadi untuk memenuhi syarat dengan aman hasil yang ditetapkan untuk jenis yang dapat di-load maka sesuai dengan artikel Phil Haacked ini Dapatkan Semua Jenis dalam Majelis dan kode Jon Skeet Anda malah akan melakukan sesuatu seperti:
Lalu:
sumber
CreateInstance
untuk mereka semua, dan pengecualian dilemparkan ketika mencoba membuat antarmuka yang sebenarnya (yang membuat saya bingung untuk sementara waktu ketika saya pikir antarmuka yang sebenarnya tidak sesuai dengan solusi ini). Jadi saya mengubah kode menjadiGetLoadableTypes(assembly).Where(interfaceType.IsAssignableFrom).Where(t => !(t.Equals(interfaceType))).ToList();
.Jawaban lain di sini digunakan
IsAssignableFrom
. Anda juga dapat menggunakanFindInterfaces
dariSystem
namespace, seperti dijelaskan di sini .Berikut adalah contoh yang memeriksa semua majelis di folder majelis yang saat ini menjalankan, mencari kelas yang mengimplementasikan antarmuka tertentu (menghindari LINQ untuk kejelasan).
Anda dapat mengatur daftar antarmuka jika Anda ingin mencocokkan lebih dari satu.
sumber
loop melalui semua rakitan yang dimuat, loop melalui semua tipenya, dan periksa apakah mereka mengimplementasikan antarmuka.
sesuatu seperti:
sumber
Ini berfungsi untuk saya (jika Anda mau, Anda dapat mengecualikan jenis sistem dalam pencarian):
sumber
Sunting: Saya baru saja melihat hasil edit untuk mengklarifikasi bahwa pertanyaan awal adalah untuk pengurangan iterasi / kode dan itu semua baik dan bagus sebagai latihan, tetapi dalam situasi dunia nyata Anda akan menginginkan implementasi tercepat, terlepas dari bagaimana kerennya tampilan LINQ yang mendasarinya.
Inilah metode Utils saya untuk iterasi melalui tipe yang dimuat. Ini menangani kelas reguler serta antarmuka, dan opsi excludeSystemTypes mempercepat segalanya jika Anda mencari implementasi dalam basis kode Anda sendiri / pihak ketiga.
Tidak cantik, saya akui.
sumber
excludeSystemTypes
dua kali dalam satuif
?Jawaban lain tidak berfungsi dengan antarmuka umum .
Yang ini, cukup ganti typeof (ISomeInterface) dengan typeof (T).
Begitu juga dengan
kami mendapatkan semua majelis
digunakan untuk mengecualikan antarmuka dan yang abstrak dan
untuk memilikinya dalam daftar.
sumber
Tidak ada cara mudah (dalam hal kinerja) untuk melakukan apa yang ingin Anda lakukan.
Refleksi bekerja dengan rakitan dan tipe terutama sehingga Anda harus mendapatkan semua jenis rakitan dan meminta mereka untuk antarmuka yang tepat. Ini sebuah contoh:
Itu akan memberi Anda semua jenis yang menerapkan IMyInterface di Majelis MyAssembly
sumber
Bahkan lebih baik ketika memilih lokasi Majelis. Saring sebagian besar rakitan jika Anda tahu semua antarmuka yang Anda implementasikan berada dalam Assembly.DefinedTypes yang sama.
Oleh Can Bilgin
sumber
Metode OfType Linq dapat digunakan tepat untuk skenario semacam ini:
https://docs.microsoft.com/fr-fr/dotnet/api/system.linq.enumerable.oftype?view=netframework-4.8
sumber
Sudah ada banyak jawaban yang valid tetapi saya ingin menambahkan implementasi anther sebagai ekstensi Jenis dan daftar tes unit untuk menunjukkan skenario yang berbeda:
Algoritma ini mendukung skenario berikut:
sumber
sumber
Saya mendapat pengecualian dalam kode-linq jadi saya melakukannya dengan cara ini (tanpa ekstensi yang rumit):
sumber
Anda bisa menggunakan beberapa LINQ untuk mendapatkan daftar:
Tapi sungguh, apakah itu lebih mudah dibaca?
sumber