C# – Load all types that implement an interface in the current assembly

To get all types in the current assembly that implement a specified interface, use the following:

private IEnumerable<Type> GetAllTypesThatImplementInterface<T>()
{
	return System.Reflection.Assembly.GetExecutingAssembly()
		.GetTypes()
		.Where(type => typeof(T).IsAssignableFrom(type) && !type.IsInterface);
}

To create instances of these types, loop through them and use Activator.CreateInstance(), like so:

foreach (var type in GetAllTypesThatImplementInterface<T>())
{
	var instance = (T)Activator.CreateInstance(type);

	//do something with instance
}

Example – Auto-wire a command routing table

Let’s say we want to build a command routing table. We have commands and want to automatically wire up the command handlers.

This is similar to how web APIs work. You specify which route a controller handles. When a request comes in, the web framework automatically calls the controller that handles that route.

Create the Command Handler interface

public interface ICommandHandler
{
	string HandlesCommand { get; }
	void Handle(string command, string data);
}

Create the command routing table

This loads all types that implement the ICommandHandler interface, creating a map of command => command handler.

public class CommandRoutingTableBuilder
{
	public Dictionary<string, ICommandHandler> GetCommandRoutingTable()
	{
		var commandRoutingTable = new Dictionary<string, ICommandHandler>();

		foreach (var type in GetAllTypesThatImplementInterface<ICommandHandler>())
		{
			var handler = (ICommandHandler)Activator.CreateInstance(type);

			commandRoutingTable.Add(handler.HandlesCommand, handler);
		}

		return commandRoutingTable;
	}
	private IEnumerable<Type> GetAllTypesThatImplementInterface<T>()
	{
		return System.Reflection.Assembly.GetExecutingAssembly()
			.GetTypes()
			.Where(type => typeof(T).IsAssignableFrom(type) && !type.IsInterface);
	}
}

Implement a command handler

To show this working we’ll create a simple command handler. It handles the “repeat” command by writing the data twice to the console.

public class RepeatDataCommandHandler : ICommandHandler
{
	public string HandlesCommand => "repeat";

	public void Handle(string command, string data)
	{
		Console.WriteLine($"I repeat: {data} {data}");
	}
}

Example of using the routing table to automatically handle a command

static void Main(string[] args)
{
	var commandRoutingTable = new CommandRoutingTableBuilder().GetCommandRoutingTable();

	string command = "repeat";
	string data = "hello world";

	commandRoutingTable[command].Handle(command, data);
}

Because RepeatDataCommandHandler is mapped to the “repeat” command, this code calls RepeatDataCommandHandler.Handle(), which outputs “I repeat: hello world hello world” to the console.

Leave a Comment