Bagaimana menemukan semua tipe dalam sebuah Majelis yang Mewarisi dari Tipe Tertentu C #

92

Bagaimana Anda mendapatkan koleksi dari semua jenis yang mewarisi dari jenis tertentu lainnya?

aceinthehole
sumber

Jawaban:

150

Sesuatu seperti:

public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
    return assembly.GetTypes().Where(t => baseType.IsAssignableFrom(t));
}

Jika Anda perlu menangani generik, itu menjadi agak rumit (misalnya meneruskan List<>tipe terbuka tetapi mengharapkan untuk mendapatkan kembali tipe yang diturunkan dari List<int>). Kalau tidak, itu sederhana :)

Jika Anda ingin mengecualikan jenis itu sendiri, Anda dapat melakukannya dengan cukup mudah:

public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
    return assembly.GetTypes().Where(t => t != baseType && 
                                          baseType.IsAssignableFrom(t));
}

Perhatikan bahwa ini juga akan memungkinkan Anda untuk menentukan antarmuka dan menemukan semua tipe yang mengimplementasikannya, daripada hanya bekerja dengan kelas seperti Type.IsSubclassOfhalnya.

Jon Skeet
sumber
2
Terima kasih! Saya akhirnya menggunakan Terima kasih ini - saya akhirnya menggunakan Daftar statis publik ini <Type> GetAllSubclassesOf (Type baseType) {return Assembly.GetAssembly (baseType) .GetTypes (). Di mana (type => type.IsSubclassOf (baseType)). ToList (); }
aceinthehole
@Downvoter di sini. Komentar saya hilang. Seperti yang ditunjukkan oleh aceinthehole jawabannya salah. Saya telah menambahkan jawaban yang benar karena saya melewatkan komentar ace sampai saya menemukan kodenya tidak berfungsi. Selamat Natal.
Tim Murphy
@Tim: Ini tidak salah, ini sedikit berbeda. IsAssignableFromharus bekerja dengan baik. Secara khusus, versi saya juga menangani antarmuka. Apakah Anda menguji kode saya? Pada kasus apa jawaban saya gagal?
Jon Skeet
1
@On. Metode Anda benar-benar menangani antarmuka. Saya seorang programmer VB, kami mewarisi kelas dan mengimplementasikan antarmuka. Apakah ini berbeda di C #? Saya bertanya karena pertanyaannya, seperti yang saya butuhkan, menginginkan tipe yang mewarisi tipe, bukan menerapkan tipe.
Tim Murphy
2
@ Tim: Dalam C # kita hanya menggunakan ":" untuk keduanya ... tapi saya biasanya akan mempertimbangkan antarmuka sebagai bagian dari hierarki pewarisan suatu tipe.
Jon Skeet
27

Metode berikut akan mendapatkan kumpulan tipe yang mewarisi tipe.

C #

public IEnumerable<Type> FindSubClassesOf<TBaseType>()
{   
    var baseType = typeof(TBaseType);
    var assembly = baseType.Assembly;

    return assembly.GetTypes().Where(t => t.IsSubclassOf(baseType));
}

VB.NET

Public Function FindSubClasses(Of TBaseType)() As IEnumerable(Of Type)

    Dim baseType = GetType(TBaseType)
    Dim assembly = baseType.Assembly

    Return From t In assembly.GetTypes() 
           Where t.IsSubClassOf(baseType) 
           Select t

End Function

Jika Anda perlu menyertakan tipe yang mengimplementasikan antarmuka, lihat jawaban @Jon Skeet.

Tim Murphy
sumber
1

Anda harus menghitung semua jenis dan memeriksa masing-masing apakah itu mewarisi yang Anda cari.

Beberapa kode seperti yang ada di pertanyaan ini semoga bermanfaat untuk Anda.

Thomas Danecker
sumber
1

Pertimbangkan untuk menggunakan metode ini (ditulis untuk PCL):

public IEnumerable<Type> FindDerivedTypes( Assembly assembly, Type baseType )
{
        TypeInfo baseTypeInfo = baseType.GetTypeInfo();
        bool isClass = baseTypeInfo.IsClass, isInterface = baseTypeInfo.IsInterface;

        return
            from type in assembly.DefinedTypes
            where isClass ? type.IsSubclassOf( baseType ) :
                  isInterface ? type.ImplementedInterfaces.Contains( baseTypeInfo.AsType() ) : false
            select type.AsType();
}
HappyNomad
sumber