Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Dal punto di vista della reflection, la differenza tra un tipo generico e un tipo comune è che a un tipo generico è associato un set di parametri di tipo (se si tratta di una definizione di tipo generico) o argomenti di tipo (se si tratta di un tipo costruito). Un metodo generico è diverso da un metodo ordinario nello stesso modo.
Esistono due chiavi per comprendere come la reflection gestisce i tipi e i metodi generici:
I parametri di tipo delle definizioni di tipo generico e delle definizioni di metodi generici sono rappresentati dalle istanze della Type classe .
Annotazioni
Molti metodi e proprietà di Type hanno un comportamento diverso quando un Type oggetto rappresenta un parametro di tipo generico. Queste differenze sono documentate negli articoli sulle proprietà e sui metodi. Ad esempio, vedere IsAutoClass e DeclaringType. Inoltre, alcuni membri sono validi solo quando un Type oggetto rappresenta un parametro di tipo generico. Ad esempio, vedere GetGenericTypeDefinition.
Se un'istanza di Type rappresenta un tipo generico, include una matrice di tipi che rappresentano i parametri di tipo (per le definizioni di tipi generici) o gli argomenti di tipo (per i tipi costruiti). Lo stesso vale per un'istanza della MethodInfo classe che rappresenta un metodo generico.
Reflection fornisce metodi di Type e MethodInfo che consentono di accedere all'array di parametri di tipo e di determinare se un'istanza di Type rappresenta un parametro di tipo o un tipo effettivo.
Per un esempio di codice che illustra i metodi descritti qui, vedere Come esaminare e creare istanze di tipi generici con Reflection.
La discussione seguente presuppone la familiarità con la terminologia dei generics, ad esempio la differenza tra parametri di tipo e argomenti e tipi costruiti aperti o chiusi. Per altre informazioni, vedere Generics.
Si tratta di un tipo o di un metodo generico?
Quando si usa la reflection per esaminare un tipo sconosciuto, rappresentato da un'istanza di Type, utilizzare la IsGenericType proprietà per determinare se il tipo sconosciuto è generico. Restituisce true
se il tipo è generico. Analogamente, quando si esamina un metodo sconosciuto, rappresentato da un'istanza della MethodInfo classe , utilizzare la IsGenericMethod proprietà per determinare se il metodo è generico.
Si tratta di una definizione di metodo o di tipo generico?
Utilizzare la IsGenericTypeDefinition proprietà per determinare se un Type oggetto rappresenta una definizione di tipo generico e utilizzare il IsGenericMethodDefinition metodo per determinare se un oggetto MethodInfo rappresenta una definizione di metodo generico.
Le definizioni di tipi e metodi generici sono i modelli da cui vengono creati tipi istanziabili. I tipi generici nelle librerie .NET, ad esempio Dictionary<TKey,TValue>, sono definizioni di tipi generici.
Il tipo o il metodo è aperto o chiuso?
Un tipo o un metodo generico viene chiuso se sono stati sostituiti tipi istanziabili per tutti i relativi parametri di tipo, inclusi tutti i parametri di tipo di tutti i tipi contenitori. È possibile creare un'istanza di un tipo generico solo se è chiusa. La Type.ContainsGenericParameters proprietà restituisce true
se un tipo è aperto. Per i metodi, il MethodBase.ContainsGenericParameters metodo esegue la stessa funzione.
Generare tipi generici chiusi
Dopo aver creato una definizione di tipo o metodo generico, usare il MakeGenericType metodo per creare un tipo generico chiuso o il MakeGenericMethod metodo per creare un MethodInfo oggetto per un metodo generico chiuso.
Ottenere la definizione del tipo o del metodo generico
Se si dispone di un tipo o un metodo generico aperto che non è una definizione di tipo o metodo generico, non è possibile crearne istanze e non è possibile specificare i parametri di tipo mancanti. È necessario avere una definizione di tipo o metodo generico. Utilizzare il GetGenericTypeDefinition metodo per ottenere la definizione di tipo generico o il GetGenericMethodDefinition metodo per ottenere la definizione del metodo generico.
Ad esempio, se si dispone di un Type oggetto che rappresenta Dictionary<int, string>
e si desidera creare il tipo Dictionary<string, MyClass>
, è possibile utilizzare il GetGenericTypeDefinition metodo per ottenere un Type oggetto che rappresenta Dictionary<TKey, TValue>
e quindi utilizzare il MakeGenericType metodo per produrre un Type oggetto che rappresenta Dictionary<int, MyClass>
.
Per un esempio di tipo generico aperto che non è un tipo generico, vedere Parametro di tipo o argomento di tipo.
Esaminare gli argomenti di tipo e i parametri di tipo
Utilizzare il Type.GetGenericArguments metodo per ottenere una matrice di oggetti che rappresentano i parametri di Type tipo o gli argomenti di tipo di un tipo generico e utilizzare il MethodInfo.GetGenericArguments metodo per eseguire la stessa operazione per un metodo generico.
Dopo aver appreso che un Type oggetto rappresenta un parametro di tipo, è possibile rispondere a molte domande aggiuntive. È possibile determinare l'origine del parametro di tipo, la relativa posizione e i relativi vincoli.
Parametro di tipo o argomento di tipo
Per determinare se un particolare elemento della matrice è un parametro di tipo o un argomento di tipo, utilizzare la IsGenericParameter proprietà . La IsGenericParameter proprietà è true
se l'elemento è un parametro di tipo.
Un tipo generico può essere aperto senza essere una definizione di tipo generico, nel qual caso ha una combinazione di argomenti di tipo e parametri di tipo. Nel codice seguente, ad esempio, la classe D
deriva da un tipo creato sostituendo il primo parametro di tipo di D
per il secondo parametro di tipo di B
.
class B<T, U> {}
class D<V, W> : B<int, V> {}
Class B(Of T, U)
End Class
Class D(Of V, W)
Inherits B(Of Integer, V)
End Class
Se si ottiene un Type oggetto che rappresenta D<V, W>
e si usa la proprietà per ottenere il BaseType tipo di base, il risultato type B<int, V>
è aperto, ma non è una definizione di tipo generico.
Origine di un parametro generico
Un parametro di tipo generico può provenire dal tipo che si sta esaminando, da un tipo contenitore o da un metodo generico. È possibile determinare l'origine del parametro di tipo generico come indicato di seguito:
- Usare prima di tutto la DeclaringMethod proprietà per determinare se il parametro di tipo proviene da un metodo generico. Se il valore della proprietà non è un riferimento Null, l'origine è un metodo generico.
- Se l'origine non è un metodo generico, utilizzare la DeclaringType proprietà per determinare il tipo generico a cui appartiene il parametro di tipo generico.
Se il parametro di tipo appartiene a un metodo generico, la DeclaringType proprietà restituisce il tipo che ha dichiarato il metodo generico, che è irrilevante.
Posizione di un parametro generico
In rari casi, è necessario determinare la posizione di un parametro di tipo nell'elenco dei parametri di tipo della relativa classe dichiarante. Si supponga, ad esempio, di avere un Type oggetto che rappresenta il B<int, V>
tipo dell'esempio precedente. Il GetGenericArguments metodo fornisce un elenco di argomenti di tipo e, quando si esamina V
, è possibile usare le proprietà DeclaringMethod e DeclaringType per individuare la provenienza. È quindi possibile utilizzare la proprietà per determinarne la GenericParameterPosition posizione nell'elenco dei parametri di tipo in cui è stata definita. In questo esempio, V
si trova nella posizione 0 (zero) nell'elenco dei parametri di tipo in cui è stato definito.
Vincoli di tipo e interfaccia di base
Utilizzare il GetGenericParameterConstraints metodo per ottenere il vincolo del tipo di base e i vincoli di interfaccia di un parametro di tipo. L'ordine degli elementi della matrice non è significativo. Un elemento rappresenta un vincolo di interfaccia se si tratta di un tipo di interfaccia.
Attributi dei parametri generici
La GenericParameterAttributes proprietà ottiene un GenericParameterAttributes valore che indica la varianza (covarianza o controvarianza) e i vincoli speciali di un parametro di tipo.
Covarianza e controvarianza
Per determinare se un parametro di tipo è covariante o controvariante, applicare la GenericParameterAttributes.VarianceMask maschera al GenericParameterAttributes valore restituito dalla GenericParameterAttributes proprietà . Se il risultato è GenericParameterAttributes.None, il parametro di tipo è invariante. Per altre informazioni, vedere Covarianza e Controvarianza.
Vincoli speciali
Per determinare i vincoli speciali di un parametro di tipo, applicare la GenericParameterAttributes.SpecialConstraintMask maschera al GenericParameterAttributes valore restituito dalla GenericParameterAttributes proprietà . Se il risultato è GenericParameterAttributes.None, non sono presenti vincoli speciali. Un parametro di tipo può essere vincolato a un tipo riferimento, a un tipo di valore non nullable e a un costruttore senza parametri.
Invarianti
Per una tabella delle condizioni invarianti per i termini comuni in reflection per i tipi generici, vedere Type.IsGenericType. Per altri termini relativi ai metodi generici, vedere MethodBase.IsGenericMethod.