Getting Types Implementing Class or Interface
Friday, June 5th 2009 — Programming, C#
I've worked on a couple of applications that support plugins, and wanted a way to automagically get all the classes that implement by base plugin class/interface. Using LINQ in C# 3.5 this is really easy to do!
Check out the following piece of code:
/// <summary>
/// Gets all the types implementing the Type.
/// </summary>
public static IEnumerable<Type> GetImplementors(this Type implementee)
{
var types = from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.GetTypes()
where t != implementee && implementee.IsAssignableFrom(t)
select t;
return types;
}
As you can see, it's implemented as an extension method. Stick it in a static class and you'll be able to do the following:
var plugins = typeof(PluginBase).GetImplementors();
This piece of code has been of use to me on several occasions. Just consider that it'll also return interfaces and abstract classes (which, of course, cannot be instantiated) that implement the type.
Another piece of code useful when working with types is the following shortcut to get an instance of a type:
/// <summary>
/// Gets an instance of the Type using the constructor that matches the given type
/// signature and with the given parameters.
/// </summary>
/// <typeparam name="T">The Type to instantiate.</typeparam>
/// <param name="types">The type signature of the constructor to use.</param>
/// <param name="args">The parameters to use when invoking the constructor.</param>
public static T GetInstance<T>(Type[] types, params object[] args)
{
return (T)typeof(T).GetConstructor(types).Invoke(args);
}
/// <summary>
/// Gets an instance of the Type using the given parameters.
/// </summary>
/// <typeparam name="T">The Type to instantiate.</typeparam>
/// <param name="args">
/// The parameters to use when invoking the constructor. The types of the parameters
/// will be used to determine the type signature.
/// </param>
public static T GetInstance<T>(params object[] args)
{
return (T)typeof(T).GetInstance(args);
}
/// <summary>
/// Gets an instance of the Type using the constructor that matches the given type
/// signature and with the given parameters.
/// </summary>
/// <param name="type">The Type to instantiate.</param>
/// <param name="types">The type signature of the constructor to use.</param>
/// <param name="args">The parameters to use when invoking the constructor.</param>
public static object GetInstance(this Type type, Type[] types, params object[] args)
{
return type.GetConstructor(types).Invoke(args);
}
/// <summary>
/// Gets an instance of the Type using the given parameters.
/// </summary>
/// <param name="type">The Type to instantiate.</param>
/// <param name="args">
/// The parameters to use when invoking the constructor. The types of the parameters
/// will be used to determine the type signature.
/// </param>
public static object GetInstance(this Type type, params object[] args)
{
Type[] types = new Type[args.Length];
for (int i = 0; i < args.Length; i++)
types[i] = args[i] == null ? typeof(object) : args[i].GetType();
return type.GetInstance(types, args);
}
Just call it like so:
var instance = Types.GetInstance<MyPlugin>();
If you only have the Type instance, you can use the extension method:
var instance = (PluginBase)typeInstance.GetInstance();