2011-12-14 8 views
30

Ho un programma C#, come posso verificare in fase di esecuzione se esiste uno spazio dei nomi, una classe o un metodo? Inoltre, come creare un'istanza di una classe usando il suo nome sotto forma di stringa?C# - Come verificare se spazio dei nomi, classe o metodo esiste in C#?

Pseudocodice:

string @namespace = "MyNameSpace"; 
string @class = "MyClass"; 
string method= "MyMEthod"; 

var y = IsNamespaceExists(namespace); 
var x = IsClassExists(@class)? new @class : null; //Check if exists, instantiate if so. 
var z = x.IsMethodExists(method); 
+0

Ricordatevi di indicare la risposta più appropriata come risposta. –

risposta

39

È possibile utilizzare Type.GetType(string) per riflettere una classe. Type ha metodi per scoprire altri membri, incluso un metodo, disponibili per quel tipo.

Un trucco, tuttavia, è che GetType desidera un nome qualificato dell'assemblaggio. Se si utilizza solo il nome della classe stessa, si presume che si stia facendo riferimento all'assieme corrente.

Quindi, se si voleva trovare il tipo in tutti gli assembly caricati, si può fare qualcosa di simile (utilizzando LINQ):

var type = (from assembly in AppDomain.CurrentDomain.GetAssemblies() 
      from type in assembly.GetTypes() 
      where type.Name == className 
      select type); 

Naturalmente, ci possono essere più ad esso che quello, in cui si Voglio riflettere sugli assembly di riferimento che potrebbero non essere ancora caricati, ecc.

Come per determinare gli spazi dei nomi, la riflessione non li esporta distintamente. Invece, dovreste fare qualcosa di simile:

var namespaceFound = (from assembly in AppDomain.CurrentDomain.GetAssemblies() 
from type in assembly.GetTypes() 
where type.Namespace == namespace 
select type).Any() 

Mettere tutto insieme, devi avere qualcosa di simile:

var type = (from assembly in AppDomain.CurrentDomain.GetAssemblies() 
       from type in assembly.GetTypes() 
       where type.Name == className && type.GetMethods().Any(m => m.Name == methodName) 
       select type).FirstOrDefault(); 

if (type == null) throw new InvalidOperationException("Valid type not found."); 

object instance = Activator.CreateInstance(type); 
+2

E come stabiliresti se esiste uno spazio dei nomi con i tuoi esempi? –

+0

Aggiornato la mia risposta. Controlla il secondo esempio di codice. Enumeriamo ciascun assembly caricato e ogni tipo in ciascun assembly e cerchiamo qualsiasi tipo che abbia il nome dello spazio dei nomi desiderato. – HackedByChinese

+1

Se si desidera verificare che lo spazio dei nomi sia valido, il nome della classe è valido e la classe ha un metodo, è possibile farlo tutto in una volta con il terzo esempio di codice. basta cambiare dove type.Name == className su qualcosa come 'where type.FullName == string.Format (" {0}. {1} ", namespace, className) && type.GetMethods(). Any (m => m .Name == methodName) '. Inoltre, ho fatto un errore in quegli esempi tralasciando la parte 'select' dell'istruzione. corretto. – HackedByChinese

2

Una sola parola: Reflection. Ad eccezione di Namespace, dovrai analizzare quelli con i nomi dei tipi.

MODIFICA: Colpire che - per gli spazi dei nomi è necessario utilizzare la proprietà Type.Namespace per determinare a quale spazio dei nomi appartiene ogni classe. (Vedere HackedByChinese response per ulteriori informazioni).

+0

+1 Grazie! La riflessione sembra interessante. – dpp

25

È possibile risolvere uno Type da una stringa utilizzando il metodo Type.GetType(String). Per esempio:

Type myType = Type.GetType("MyNamespace.MyClass"); 

È quindi possibile utilizzare questa istanza Tipo di verificare se un metodo esiste sul tipo chiamando il metodo GetMethod(String). Per esempio:

MethodInfo myMethod = myType.GetMethod("MyMethod"); 

Sia GetType e GetMethod ritorno null se nessun tipo o il metodo è stato trovato per il nome dato, in modo da poter verificare se il tipo/metodo esiste controllando se la vostra chiamata di metodo restituito null o non.

Infine, è possibile creare un'istanza utilizzando il tipo di Activator.CreateInstance(Type) Ad esempio:

object instance = Activator.CreateInstance(myType); 
+1

Questa è una risposta molto più rapida e concisa rispetto a quella contrassegnata come corretta sopra. Girare ogni tipo in ogni assemblea è dolorosamente lento. Se si includono tutti gli assembly di sistema, potrebbe trattarsi di un ciclo di iterazione da 10.000. – Deane

Problemi correlati