Friday, July 20, 2007

Finding the interfaces you want

This is a simple little .NET reflection trick, but one which not a lot of people realize how to do (I get asked about this a lot). Suppose you want to search an assembly for all the types that implement a given interface. For example, your application supports plug-ins and you want to load a third-party assembly that potentially contains plug-in classes that implement your plug-in interface.

C#:

Assembly assembly = Assembly.LoadFile(@"C:\path\to\3rdparty\plug-in.dll");
foreach (Type type in assembly.GetTypes())
{
if (typeof(IMyPlugin).IsAssignableFrom(type))
{
IMyPlugin plugin = (IMyPlugin)assembly.CreateInstance(type.FullName);
// do something with the plugin ...
}
}


VB.NET:

Dim assembly As Assembly = Assembly.LoadFile("C:\path\to\3rdparty\plug-in.dll");
Dim type As Type
For Each type In assembly.GetTypes()
If GetType(IMyPlugin).IsAssignableFrom(type)
Dim plugin As IMyPlugin = CType(assembly.CreateInstance(type.FullName), IMyPlugin)
' do something with the plugin ...
End If
Next


It's pretty straightforward. First, we use the Assembly object to load the third party assembly from its DLL. Then, we use the Assembly.GetTypes() method to iterate through all of the classes present in the assembly. Inside the loop, we use Type.IsAssignableFrom() to determine whether the class can be assigned to our IMyPlugin interface. Finally, we create an instance of the class and assign it to a variable of type IMyPlugin so that we can actually do something with it (note that the above code assumes the class has a parameterless constructor).

Note that you want to check the possibilty of assignment in the order shown above, i.e. typeof(interface).IsAssignableFrom(class). If you do it the other way around, it won't work. Basically this statement is testing to see if this is possible:

C#:

interface variableName = new class();


VB.NET:

Dim variableName As interface = New class()