C# – Carica tutti i tipi che implementano un'interfaccia nell'assembly corrente

C# – Carica tutti i tipi che implementano un'interfaccia nell'assembly corrente

Per ottenere tutti i tipi nell'assembly corrente che implementano un'interfaccia specifica, utilizzare quanto segue:

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

Per creare istanze di questi tipi, scorreli e usa Activator.CreateInstance(), in questo modo:

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

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

Esempio:cablare automaticamente una tabella di instradamento dei comandi

Diciamo che vogliamo costruire una tabella di routing dei comandi. Abbiamo comandi e vogliamo collegare automaticamente i gestori dei comandi.

Questo è simile a come funzionano le API web. Specificare quale route gestisce un controller. Quando arriva una richiesta, il framework web chiama automaticamente il controller che gestisce quel percorso.

Crea l'interfaccia del gestore dei comandi

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

Crea la tabella di instradamento dei comandi

Questo carica tutti i tipi che implementano l'interfaccia ICommandHandler, creando una mappa di comando => gestore di comandi.

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)

Implementa un comando gestore

Per mostrare questo funzionamento creeremo un semplice gestore di comandi. Gestisce il comando "repeat" scrivendo i dati due volte sulla console.

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)

Esempio di utilizzo della tabella di routing per gestire automaticamente un comando

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)

Poiché RepeatDataCommandHandler è mappato al comando "repeat", questo codice chiama RepeatDataCommandHandler.Handle(), che restituisce "I repeat:hello world hello world" alla console.