2010-03-02 5 views
19

In numerosi luoghi, ho incontrato nomi di tipi parzialmente qualificati del modulo FullTypeName, AssemblyName, ad esempio Type.AssemblyQualifiedName solo senza i qualificatori versione, cultura e publicKeyToken.Come Type.GetType funziona quando viene fornito un nome di tipo parzialmente qualificato?

La mia domanda è come si può convertirlo al rispettivo Type con un minimo di sforzo? Ho pensato che lo Type.GetType svolgesse il lavoro, ma purtroppo no. Il codice seguente, ad esempio, torna null:

Type.GetType("System.Net.Sockets.SocketException, System"); 

Naturalmente, se a specificare il nome completo funziona:

Type.GetType("System.Net.Sockets.SocketException, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); 

Grazie mille.

+0

Avete il tipo in fase di compilazione? In caso affermativo, perché non utilizzare typeof () .FullName, et. al? Se si dispone del tipo in fase di esecuzione, è possibile utilizzare .GetType(). FullName et. al. O mi manca la richiesta specifica? Ho capito che vuoi solo specificare un nome parziale, ma questo è molto più per il caricatore che per il sistema di tipi. I FQN servono a chiarire i problemi di riferimento per le rare occasioni in cui si verificano conflitti di nome, il che è verosimilmente più frequente negli assembly utente che negli assembly BCL. – GrayWizardx

+1

Sono perfettamente a conoscenza di typeof() o Type.FullName. Il tipo dell'oggetto viene letto da un file di configurazione, ecco perché uso Type.GetType. Ed è per questo che sono così interessato a capire come funzionano i nomi di tipi parzialmente qualificati. – mark

risposta

8

Se la DLL in cui si trova non è già stata caricata nel dominio dell'applicazione (ad esempio, è stata utilizzata), è necessario il percorso completo come questo, se è già caricato, può trovarlo con la versione più breve.

Per rispondere alla tua domanda: la seconda versione funziona sempre, mantienila e hai un modo di preoccuparti.

+1

Non penso sia importante che l'assembly sia già caricato o meno - la versione breve non funzionerà. Il nome qualificato dello spazio dei nomi funzionerà se il tipo è nell'assembly in esecuzione o in mscorlib. Spiegazione più completa di seguito. – lesscode

2

codice a lavorare con la forma breve è:

Assembly a = Assembly.LoadWithPartialName(assemblyName); 
    Type t = a.GetType(typeName); 

ma LoadWithPartialName è deprecato, quindi credo che si dovrebbe attaccare con la forma a lungo.

29

Se il gruppo è stato caricato nel dominio corrente, allora il codice qui sotto solito funziona:

public static Type GetTypeEx(string fullTypeName) 
{ 
    return Type.GetType(fullTypeName) ?? 
      AppDomain.CurrentDomain.GetAssemblies() 
        .Select(a => a.GetType(fullTypeName)) 
        .FirstOrDefault(t => t != null); 
} 

Si può usare in questo modo:

Type t = GetTypeEx("System.Net.Sockets.SocketException"); 
+1

Grazie mille per questa risposta! È esattamente quello che stavo cercando, molto meglio della risposta "accettata". –

+2

Ricorda solo che potrebbe essere molto lento, quindi non dimenticare di memorizzare nella cache .. – nawfal

2

Avendo appena passato attraverso un problema simile con qualche codice legacy, non penso che la prima affermazione nella risposta accettata sia corretta. Non importa se l'assemblaggio è già caricato o meno.

Secondo la documentazione, Type.GetType(string) richiede un AssemblyQualifiedName, a meno che il tipo in questione si trovi nell'assembly attualmente in esecuzione o in mscorlib, nel qual caso il nome del tipo qualificato per lo spazio dei nomi è tutto ciò che è richiesto.

Si noti che un AssemblyQualifiedName include il DisplayName completo dell'assembly del tipo (con versione, cultura e token di chiave pubblica).

La versione breve non funzionerà se non si intercetta il caricamento del tipo non riuscito con un numero personalizzato AssemblyResolver (che in realtà era il caso del mio problema, mascherando un altro problema).

0

Vero, Type.GetType (stringa) richiede un nomeQualified assembly.Questo può essere in molte forme:

MyNS.MyType, MyAssembly, Version=x.x.x.x, Culture=xxx, PublicKeyToken=XXXXXXXXXX 

Di seguito sono anche AssemblyQualifiedNames validi:

MyNS.MyType, MyAssembly, Version=x.x, Culture=xxx, PublicKeyToken=XXXXXXXXXX 
MyNS.MyType, MyAssembly, Culture=xxx, PublicKeyToken=XXXXXXXXXX 
MyNS.MyType, MyAssembly, PublicKeyToken=XXXXXXXXXX 
MyNS.MyType, MyAssembly 

Per un assembly firmato, il minimo necessario per un FullyQualifiedAssemblyName è:

MyNS.MyType, MyAssembly, PublicKeyToken=XXXXXXXXXX 

Per assemblaggio senza firma, il minimo richiesto per un NomeCompleto FullyQualified è:

MyNS.MyType, MyAssembly 

Non è necessario che tutto il "movimento della mano" si accenda nei frammenti di codice che altri hanno fornito. Assicurarsi che i nomi dei tipi siano impostati correttamente e che sia possibile accedere ai tipi (e caricare gli assiemi in modo dinamico) con un alto grado di flessibilità. Lo faccio regolarmente.

Nell'esempio di OP utilizzando:

Type.GetType("System.Net.Sockets.SocketException, System") 

Il motivo dell'errore è stata l'assenza del PublicKeyToken. Gli assembly .Net FW sono tutti firmati e pertanto richiedono il PublicKeyToken per risolvere il nome dell'assembly. Quello che segue funzionerebbe:

Type.GetType("System.Net.Sockets.SocketException, System, PublicKeyToken=b77a5c561934e089") 
Problemi correlati