Condividi tramite


Metodi System.Type.GetType

Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.

Usare l'overload del GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>, Boolean, Boolean) metodo e gli overload associati (GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>) e GetType(String, Func<AssemblyName,Assembly>, Func<Assembly,String,Boolean,Type>, Boolean)) per sostituire l'implementazione predefinita del GetType metodo con implementazioni più flessibili. Fornendo metodi personalizzati che risolvono i nomi dei tipi e i nomi degli assembly che li contengono, è possibile eseguire le operazioni seguenti:

  • Controllare la versione di un assembly da cui viene caricato un tipo.
  • Specificare un'altra posizione in cui cercare un nome di tipo che non include un nome di assembly.
  • Caricare moduli usando nomi di moduli parziali.
  • Restituisce sottoclassi di System.Type che non vengono create da Common Language Runtime (CLR).

Ad esempio, nella serializzazione a tolleranza di versione questo metodo consente di cercare un assembly "più adatto" usando un nome parziale. Altri overload del GetType metodo richiedono un nome di tipo qualificato dall'assembly, che include il numero di versione.

Le implementazioni alternative del sistema di tipi potrebbero dover restituire sottoclassi di System.Type che non vengono create da CLR. Tutti i tipi restituiti da altri overload del GetType metodo sono tipi di runtime.

Note sull'utilizzo

Questo overload del metodo e gli overload associati analizzano il nome di un tipo e il nome di un assembly e quindi risolvono typeName i nomi. La risoluzione del nome dell'assembly si verifica prima della risoluzione del nome del tipo, perché è necessario risolvere un nome di tipo nel contesto di un assembly.

Annotazioni

Se non si ha familiarità con il concetto di nomi di tipi qualificati dall'assembly, vedere la proprietà AssemblyQualifiedName.

Se typeName non è un nome qualificato dall'assembly, la risoluzione dell'assembly viene ignorata. I nomi dei tipi non qualificati possono essere risolti nel contesto di mscorlib.dll/System.Private.CoreLib.dll o dell'assembly attualmente in esecuzione, oppure puoi specificare facoltativamente un assembly nel parametro typeResolver. Gli effetti dell'inclusione o dell'omissione del nome dell'assembly per diversi tipi di risoluzione dei nomi vengono visualizzati come tabella nella sezione Risoluzione dei nomi misti .

Note generali sull'utilizzo:

  • Non passare metodi a assemblyResolver o typeResolver se provengono da chiamanti sconosciuti o non attendibili. Usare solo i metodi forniti o con cui si ha familiarità.

    Attenzione

    L'uso di metodi di chiamanti sconosciuti o non attendibili potrebbe comportare l'elevazione dei privilegi per il codice dannoso.

  • Se si omettono i assemblyResolver parametri e/o typeResolver , il valore del throwOnError parametro viene passato ai metodi che eseguono la risoluzione predefinita.

  • Se throwOnError è true, questo metodo genera un'eccezione TypeLoadException quando typeResolver restituisce null, e un'eccezione FileNotFoundException quando assemblyResolver restituisce null.

  • Questo metodo non intercetta le eccezioni generate da assemblyResolver e typeResolver. L'utente è responsabile di tutte le eccezioni generate dai metodi del sistema di risoluzione.

Risolvere gli assembly

Il assemblyResolver metodo riceve un AssemblyName oggetto, generato analizzando il nome dell'assembly stringa incluso in typeName. Se typeName non contiene un nome di assembly, assemblyResolver non viene chiamato e null viene passato a typeResolver.

Se assemblyResolver non viene fornito, per individuare l'assembly viene usato il probe di assembly standard. Se assemblyResolver viene specificato, il GetType metodo non esegue il sondaggio standard; in tal caso dovete assicurarvi che assemblyResolver possa gestire tutti gli assembly che gli passate.

Il assemblyResolver metodo deve restituire null se l'assembly non può essere risolto. Se assemblyResolver restituisce null, typeResolver non viene chiamato e non viene eseguita alcuna ulteriore elaborazione; inoltre, se throwOnError è true, viene generata un'eccezione FileNotFoundException .

Se l'oggetto AssemblyName passato a assemblyResolver è un nome parziale, una o più parti sono null. Ad esempio, se non ha una versione, la Version proprietà è null. Se la proprietà Version, la proprietà CultureInfo e il metodo GetPublicKeyToken restituiscono tutti null, è stato fornito solo il nome semplice dell'assembly. Il assemblyResolver metodo può utilizzare o ignorare tutte le parti del nome dell'assembly.

Gli effetti delle diverse opzioni di risoluzione degli assemblaggi vengono mostrati in una tabella nella sezione Risoluzione dei nomi misti per i nomi di tipo semplici e qualificati rispetto all'assemblaggio.

Risolvere i tipi

Se typeName non specifica un nome di assembly, typeResolver viene sempre chiamato . Se typeName specifica un nome di assembly, typeResolver viene chiamato solo quando il nome dell'assembly viene risolto correttamente. Se assemblyResolver o l'analisi standard dell'assembly restituisce null, typeResolver non viene chiamato.

Il typeResolver metodo riceve tre argomenti:

  • L'assemblaggio da cercare o null se typeName non contiene un nome di assemblaggio.
  • Nome semplice del tipo. Nel caso di un tipo annidato, si tratta del tipo contenitore più esterno. Nel caso di un tipo generico, si tratta del nome semplice del tipo generico.
  • Un valore booleano che è true se il caso dei nomi dei tipi deve essere ignorato.

L'implementazione determina la modalità di utilizzo di questi argomenti. Il typeResolver metodo deve restituire null se non è in grado di risolvere il tipo. Se typeResolver restituisce null e throwOnError è true, questo overload di GetType lancia un'eccezione TypeLoadException.

Gli effetti delle diverse opzioni di risoluzione dei tipi vengono visualizzati come tabella nella sezione Risoluzione dei nomi misti per i nomi di tipi semplici e qualificati dall'assembly.

Risolvere i tipi annidati

Se typeName è un tipo annidato, viene passato solo il nome del tipo contenitore più esterno a typeResolver. Quando typeResolver restituisce questo tipo, il GetNestedType metodo viene chiamato in modo ricorsivo fino a quando non viene risolto il tipo annidato più interno.

Risolvere i tipi generici

Viene GetType chiamato in modo ricorsivo per risolvere i tipi generici: prima di tutto per risolvere il tipo generico stesso e quindi risolvere i relativi argomenti di tipo. Se un argomento di tipo è generico, GetType viene chiamato in modo ricorsivo per risolvere i relativi argomenti di tipo e così via.

La combinazione di assemblyResolver e typeResolver che fornisci deve essere in grado di risolvere tutti i livelli di questa ricorsione. Si supponga, ad esempio, di fornire un oggetto assemblyResolver che controlla il caricamento di MyAssembly. Si supponga di voler risolvere il tipo Dictionary<string, MyType> generico (Dictionary(Of String, MyType) in Visual Basic). È possibile passare il seguente nome di tipo generico:

"System.Collections.Generic.Dictionary`2[System.String,[MyNamespace.MyType, MyAssembly]]"

Si noti che MyType è l'unico argomento di tipo qualificato dall'assembly. I nomi delle Dictionary<TKey,TValue> classi e String non sono qualificati per assembly. Il tuo typeResolver deve essere in grado di gestire un assembly o null, perché riceverà null per Dictionary<TKey,TValue> e String. Può gestire questo caso chiamando un overload del metodo GetType che accetta una stringa, poiché entrambi i nomi di tipi non qualificati si trovano in mscorlib.dll/System.Private.CoreLib.dll.

Type t = Type.GetType(test,
                      (aName) => aName.Name == "MyAssembly" ?
                          Assembly.LoadFrom(@".\MyPath\v5.0\MyAssembly.dll") : null,
                      (assem, name, ignore) => assem == null ?
                          Type.GetType(name, false, ignore) :
                              assem.GetType(name, false, ignore)
                     );
let t =
    Type.GetType(test,
        (fun aName ->
            if aName.Name = "MyAssembly" then
                Assembly.LoadFrom @".\MyPath\v5.0\MyAssembly.dll"
            else null),
        fun assem name ignr ->
            if assem = null then
                Type.GetType(name, false, ignr)
            else
                assem.GetType(name, false, ignr))

Il assemblyResolver metodo non viene chiamato per il tipo di dizionario e il tipo stringa, perché tali nomi di tipo non sono qualificati dall'assembly.

Supponiamo ora che, invece di System.String, il primo tipo di argomento generico sia YourType, da YourAssembly.

"System.Collections.Generic.Dictionary`2[[YourNamespace.YourType, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null], [MyNamespace.MyType, MyAssembly]]"

Poiché questo assembly non è né mscorlib.dll/System.Private.CoreLib.dll né l'assembly attualmente in esecuzione, non è possibile risolvere YourType senza un nome qualificato dell'assembly. assemblyResolve Poiché verrà chiamato in modo ricorsivo, deve essere in grado di gestire questo caso. Anziché restituire null per assembly diversi da MyAssembly, esegue ora un caricamento di assembly usando l'oggetto fornito AssemblyName .

Type t2 = Type.GetType(test,
                       (aName) => aName.Name == "MyAssembly" ?
                           Assembly.LoadFrom(@".\MyPath\v5.0\MyAssembly.dll") :
                           Assembly.Load(aName),
                       (assem, name, ignore) => assem == null ?
                           Type.GetType(name, false, ignore) :
                               assem.GetType(name, false, ignore), true
                      );
let t2 =
    Type.GetType(test,
        (fun aName ->
            if aName.Name = "MyAssembly" then
                Assembly.LoadFrom @".\MyPath\v5.0\MyAssembly.dll"
            else Assembly.Load aName),
        (fun assem name ignr ->
            if assem = null then
                Type.GetType(name, false, ignr)
            else
                assem.GetType(name, false, ignr)), true)

Risolvere i nomi dei tipi con caratteri speciali

Alcuni caratteri hanno significati speciali nei nomi qualificati dall'assembly. Se un nome di tipo semplice contiene questi caratteri, i caratteri causano errori di analisi quando il nome semplice fa parte di un nome qualificato dall'assembly. Per evitare gli errori di analisi, i caratteri speciali devono essere preceduti da una barra rovesciata prima di poter passare il nome completo dell'assembly al metodo GetType. Ad esempio, se un tipo è denominato Strange]Type, il carattere di escape deve essere aggiunto prima della parentesi quadrata come indicato di seguito: Strange\]Type.

Annotazioni

I nomi con tali caratteri speciali non possono essere creati in Visual Basic o C#, ma possono essere creati usando il linguaggio intermedio comune (CIL) o emettendo assembly dinamici.

Nella tabella seguente vengono illustrati i caratteri speciali per i nomi dei tipi.

Personaggio Significato
, (virgola) Delimitatore per i nomi qualificati dall'assembly.
[] (parentesi quadre) Come coppia di suffissi, indica un tipo di matrice; come coppia di delimitatori, racchiude gli elenchi di argomenti generici e i nomi qualificati di assembly.
& (ampersand) Come suffisso, indica che un tipo è un tipo riferimento.
* (asterisco) Come suffisso, indica che un tipo è un tipo di puntatore.
+ (più) Delimitatore per i tipi annidati.
\ (barra rovesciata) Carattere di escape.

Proprietà come AssemblyQualifiedName restituiscono stringhe con caratteri escape corretti. È necessario passare correttamente stringhe di escape al GetType metodo . A sua volta, il GetType metodo passa nomi di escape corretti a typeResolver e ai metodi di risoluzione dei tipi predefiniti. Se è necessario confrontare un nome con un nome senza caratteri di escape in typeResolver, è necessario rimuovere i caratteri di escape.

Risoluzione dei nomi misti

La tabella seguente riepiloga le interazioni tra assemblyResolver, typeResolvere la risoluzione dei nomi predefinita, per tutte le combinazioni di nome di tipo e nome dell'assembly in typeName:

Contenuto del nome del tipo Metodo resolver di assembly Metodo di risoluzione dei tipi Risultato
tipo, assemblaggio nullo nullo Equivale a chiamare il metodo Type.GetType(String, Boolean, Boolean) overload.
tipo, assembly fornito nullo assemblyResolver restituisce l'assembly o restituisce null se non è in grado di risolvere l'assembly. Se l'assembly viene risolto, l'overload del metodo Assembly.GetType(String, Boolean, Boolean) viene utilizzato per caricare il tipo dall'assembly; in caso contrario, non si tenta di risolvere il tipo.
tipo, assemblaggio nullo fornito Equivale a convertire il nome dell'assembly in un oggetto AssemblyName e chiamare un sovraccarico del metodo Assembly.Load(AssemblyName) per ottenere l'assembly. Se l'assembly viene risolto, viene passato a typeResolver; altrimenti, typeResolver non viene chiamato e non viene fatto alcun ulteriore tentativo di risolvere il tipo.
tipo, assemblaggio fornito fornito assemblyResolver restituisce l'assembly oppure, se non è in grado di risolverlo, restituisce null. Se l'assembly viene risolto, viene passato a typeResolver; in caso contrario, typeResolver non viene chiamato e non viene fatto alcun ulteriore tentativo di risolvere il tipo.
tipo Null, fornito nullo Equivale a chiamare il metodo overload Type.GetType(String, Boolean, Boolean). Poiché il nome dell'assembly non viene specificato, vengono cercati solo mscorlib.dll/System.Private.CoreLib.dll e l'assembly attualmente in esecuzione. Se assemblyResolver viene specificato, viene ignorato.
tipo Null, fornito fornito typeResolver viene chiamato e null viene passato per l'assemblaggio. typeResolver può fornire un tipo da qualsiasi assembly, inclusi gli assembly caricati a tale scopo. Se assemblyResolver viene specificato, viene ignorato.
assemblea Null, fornito Null, fornito Viene FileLoadException generata un'eccezione perché il nome dell'assembly viene analizzato come se fosse un nome di tipo qualificato dall'assembly. In questo modo viene restituito un nome di assembly non valido.