C# – Laden Sie alle Typen, die eine Schnittstelle in der aktuellen Assembly implementieren

C# – Laden Sie alle Typen, die eine Schnittstelle in der aktuellen Assembly implementieren

Verwenden Sie Folgendes, um alle Typen in der aktuellen Assembly abzurufen, die eine bestimmte Schnittstelle implementieren:

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

Um Instanzen dieser Typen zu erstellen, durchlaufen Sie sie und verwenden Sie Activator.CreateInstance() wie folgt:

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

	//do something with instance
}
Code language: C# (cs)

Beispiel – Automatisches Verbinden einer Befehls-Routing-Tabelle

Angenommen, wir möchten eine Befehls-Routing-Tabelle erstellen. Wir haben Befehle und möchten die Befehlshandler automatisch verdrahten.

Dies ähnelt der Funktionsweise von Web-APIs. Sie geben an, welche Route ein Controller verarbeitet. Wenn eine Anfrage eingeht, ruft das Webframework automatisch den Controller auf, der diese Route verarbeitet.

Erstellen Sie die Command Handler-Schnittstelle

public interface ICommandHandler
{
	string HandlesCommand { get; }
	void Handle(string command, string data);
}
Code language: C# (cs)

Erstellen Sie die Befehls-Routing-Tabelle

Dies lädt alle Typen, die die ICommandHandler-Schnittstelle implementieren, und erstellt eine Map von 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);
	}
}
Code language: C# (cs)

Einen Befehl implementieren Handler

Um diese Funktionsweise zu zeigen, erstellen wir einen einfachen Befehlshandler. Es handhabt den „Repeat“-Befehl, indem es die Daten zweimal auf die Konsole schreibt.

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

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

Beispiel für die Verwendung der Routing-Tabelle zur automatischen Verarbeitung eines Befehls

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

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

	commandRoutingTable[command].Handle(command, data);
}
Code language: C# (cs)

Da RepeatDataCommandHandler dem „repeat“-Befehl zugeordnet ist, ruft dieser Code RepeatDataCommandHandler.Handle() auf, der „I repeat:hello world hello world“ an die Konsole ausgibt.