Title: Find classes that implement an interface or that are descendants of a given class in C#
This example lets you find classes that are part of an inheritance or implementation hierarchy. When you enter a class or interface name and click Find, the example uses the following code to search the currently loaded assemblies for classes that are descendants of the class or interface.
private void btnFind_Click(object sender, EventArgs e)
{
lblNumClasses.Text = "";
lstClasses.Items.Clear();
Cursor = Cursors.WaitCursor;
Refresh();
// List the loaded assemblies.
foreach (Assembly assembly in
AppDomain.CurrentDomain.GetAssemblies())
{
Console.WriteLine(assembly.GetName().Name);
}
int num_assemblies =
AppDomain.CurrentDomain.GetAssemblies().Length;
Console.WriteLine(num_assemblies.ToString() + " assemblies");
// Get the type entered.
string type_name = txtType.Text.ToLower();
var type_query =
from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
where (type.Name.ToLower() == type_name)
select type;
Type target_type = type_query.FirstOrDefault();
if (target_type != null)
{
// Get classes that are assignable to the target type.
var classes =
from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
where target_type.IsAssignableFrom(type)
select type;
// Display the classes.
foreach (Type type in classes)
{
lstClasses.Items.Add(type.Name);
}
}
// Display the number of classes.
lblNumClasses.Text = lstClasses.Items.Count.ToString() + " classes";
Cursor = Cursors.Default;
}
The code first lists the loaded assemblies in the Console window.
Next the method converts the name of the type you entered into lower case so it can ignore capitalization while examining class names. It then creates a LINQ query named type_name to search for the class or interface name that you entered. This query uses AppDomain.CurrentDomain.GetAssemblies to get the currently loaded assemblies. It uses the assemblies' GetTypes method to get the types defined by the assemblies. It examines those types and selects those where the type's name is equal to the name you entered (converted to lower case).
Having (hopefully) found the Type for the type you entered, the program defines a second LINQ query. This one starts as the other one did to find classes defined by the loaded assemblies. This time it selects the types from which the target_type that you entered can be assigned. For example, if you typed IDisposable, then the query selects the Form class because [type of IDisposable].IsAssignableFrom(Form) is true.
The program loops through the query displaying the names of the classes in the ListBox named lstClasses.
Note that the code only gets classes in the currently loaded assemblies. Running this code actually loads more assemblies, so the first time I run it, it finds 15 assemblies and 889 classes that implement IDisposable. The second time I run it, finds 20 assemblies and 925 classes that implement IDisposable.
Download the example to experiment with it and to see additional details.
|