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
dari base
tetapi base
didefinisikan dalam rakitan yang berbeda dari derived
, rakitan yang tidak dirujuk oleh rakitan pemanggil.
Jadi katakan kita memiliki:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
Jika di ClassC
dalamnya ada AssemblyC
maka kita melakukan sesuatu sesuai jawaban yang diterima:
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Maka itu akan melempar ReflectionTypeLoadException
.
Ini karena tanpa referensi ke AssemblyA
dalam AssemblyC
Anda tidak akan dapat:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
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:
public static class TypeLoaderExtensions {
public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly) {
if (assembly == null) throw new ArgumentNullException("assembly");
try {
return assembly.GetTypes();
} catch (ReflectionTypeLoadException e) {
return e.Types.Where(t => t != null);
}
}
}
Lalu:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}