Recuperare a runtime un elenco dei types definiti in un assembly è un'operazione piuttosto semplice per chi abbia un minimo di dimestichezza con reflection: è sufficiente, infatti, invocare il metodo GetTypes() della classe Assembly per ottenere come risultato un opportuno array di System.Type. Il codice seguente, ad esempio, scrive sulla console i nomi di tutti i tipi definiti nel assembly correntemente in esecuzione:
/* Runtime version */
Assembly asm = Assembly.GetExecutingAssembly();
foreach (Type t in asm.GetTypes())
Console.WriteLine(t.FullName);
Design time
Anche a design time, nella realizzazione di un UITypeEditor, si può incorrere nella necessità di recuperare tutti i tipi definiti nel progetto corrente e magari anche negli assembly che esso referenzia. In questo scenario il problema si fa parecchio più complesso, perché bisogna tener conto della possibilità che il codice su cui si sta lavorando contenga errori di sintassi o che non sia stato ancora compilato, con il risultato che l'assembly associato potrebbe non essere aggiornato o addirittura non esistere affatto.
Il designer mette a disposizione una serie di servizi i cui riferimenti possono essere ottenuti tramite un ServiceProvider (e cioè una classe che implementa l'interfaccia IServiceProvider) e il suo metodo GetService; quest'ultimo accetta come parametro un tipo, che può essere una classe o un'interfaccia, identificativo del servizio che si vuol richiedere. Per recuperare un elenco di tipi a design time, esiste un servizio specifico che rende estremamente semplice la soluzione, che altrimenti sarebbe tutt'altro che banale; esso implementa l'interfaccia ITypeDiscoveryService del namespace System.ComponentModel.Design e può essere invocato tramite lo snippet di codice che segue:
public class MyCustomUITypeEditor: UITypeEditor
{
// ... altro codice qui ...
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
// recupero un servizio che implementi ITypeDiscoveryService
ITypeDiscoveryService tds = (ITypeDiscoveryService)
provider.GetService(typeof(ITypeDiscoveryService));
// se il servizio è stato trovato, posso utilizzarne il metodo GetTypes
if (tds != null)
{
Types[] discoveredTypes = tds.GetTypes(typeof(myBaseClass), false);
// ... altro codice qui ...
}
}
}
Il metodo GetTypes esplora i tipi contenuti nel progetto correntemente in modifica e negli assembly referenziati, restituendo quindi un array di System.Type raggiungibili dal codice corrente; questo metodo accetta due parametri: il primo è un System.Type e indica una classe base che può essere utilizzata come filtro per la ricerca, mentre il secondo è un Boolean che specifica se includere o meno nella ricerca i riferimenti ad assembly memorizzati nella Global Assembly Cache.