Assembly ritirabili per la generazione di tipi dinamici
Gli assembly ritirabili sono assembly dinamici che possono essere scaricati senza scaricare il dominio dell'applicazione in cui sono stati creati. È possibile recuperare tutta la memoria gestita e non gestita usata da un assembly ritirabile e dai tipi che contiene. Le informazioni quali il nome dell'assembly vengono rimosse dalle tabelle interne.
Per abilitare lo scaricamento, usare il flag AssemblyBuilderAccess.RunAndCollect quando si crea un assembly dinamico. L'assembly è temporaneo (ovvero, non è possibile salvarlo) ed è soggetto alle limitazioni descritte nella sezione Limitazioni per gli assembly ritirabili. Quando si rilasciano tutti gli oggetti associati a un assembly ritirabile, Common Language Runtime (CLR) scarica automaticamente l'assembly. Da tutti gli altri punti di vista, gli assembly ritirabili vengono creati e usati nello stesso modo degli altri assembly dinamici.
Durata degli assembly ritirabili
La durata di un assembly ritirabile è determinata dall'esistenza di riferimenti ai tipi che contiene e agli oggetti creati da tali tipi. Common Language Runtime non scarica un assembly fino a quando esistono uno o più degli elementi seguenti (T
è qualsiasi tipo definito nell'assembly):
Istanza dell'oggetto
T
.Un'istanza di una matrice di
T
.Un'istanza di un tipo generico con
T
come uno dei relativi argomenti di tipo. Sono incluse le raccolte generiche diT
, anche se la raccolta è vuota.Un'istanza di Type o di TypeBuilder che rappresenta
T
.Importante
È necessario rilasciare tutti gli oggetti che rappresentano parti dell'assembly. Il ModuleBuilder che definisce
T
mantiene un riferimento a TypeBuilder e l'oggetto AssemblyBuilder mantiene un riferimento a ModuleBuilder, pertanto è necessario rilasciare i riferimenti a questi oggetti. Anche l'esistenza di un LocalBuilder o ILGenerator usato nella costruzione diT
impedisce lo scaricamento.Un riferimento statico a
T
da un altro tipo definito in modo dinamicoT1
che è ancora raggiungibile mediante l'esecuzione del codice. Ad esempio,T1
potrebbe derivare daT
oT
potrebbe essere il tipo di un parametro in un metodo diT1
.Un
ByRef
a un campo statico appartenente aT
.RuntimeTypeHandle, RuntimeFieldHandle o RuntimeMethodHandle che fa riferimento a
T
o a un componente diT
.Un'istanza di qualsiasi oggetto di reflection che può essere usato indirettamente o direttamente per accedere all'oggetto Type che rappresenta
T
. Ad esempio, l'oggetto Type perT
può essere ottenuto da un tipo di matrice il cui tipo di elemento èT
o da un tipo generico che haT
come argomento di tipo.Un metodo
M
nello stack di chiamate di qualsiasi thread, in cuiM
è un metodo diT
o un metodo a livello di modulo che viene definito nell'assembly.Un delegato a un metodo statico definito in un modulo dell'assembly.
Se esiste un solo elemento in questo elenco per un solo tipo o metodo nell'assembly, il runtime non è in grado di scaricare l'assembly.
Nota
Il runtime non scarica effettivamente l'assembly fino a quando non vengono eseguiti i finalizzatori per tutti gli elementi nell'elenco.
Per tener traccia della durata, si suppone che un tipo generico costruito, ad esempio List<int>
(in C#) o List(Of Integer)
(in Visual Basic), creato e usato nella generazione di un assembly ritirabile sia stato definito nell'assembly che contiene la definizione del tipo generico o in un assembly che contiene la definizione di uno dei relativi argomenti di tipo. L'assembly esatto usato è un dettaglio di implementazione e soggetto a modifiche.
Limitazioni degli assembly ritirabili
Agli assembly ritirabili si applicano le seguenti restrizioni:
Riferimenti statici
I tipi in un assembly dinamico comune non possono avere riferimenti statici a tipi definiti in un assembly ritirabile. Ad esempio, se si definisce un tipo comune che eredita da un tipo in un assembly ritirabile, viene generata un'eccezione NotSupportedException. Un tipo in un assembly ritirabile può avere riferimenti statici a un tipo in un altro assembly ritirabile, ma estende la durata dell'assembly di destinazione del riferimento alla durata dell'assembly di origine del riferimento.
Agli assembly ritirabili si applicano le seguenti restrizioni in .NET Framework:
Interoperabilità COM
Nessuna interfaccia COM può essere definita all'interno di un assembly ritirabile e nessuna istanza di tipi all'interno di un assembly ritirabile può essere convertita in oggetti COM. Un tipo in un assembly ritirabile non può fungere da COM Callable Wrapper (CCW) o da Runtime Callable Wrapper (RCW). Tuttavia, i tipi negli assembly ritirabili possono usare oggetti che implementano interfacce COM.
Platform invoke
I metodi con l'attributo DllImportAttribute non verranno compilati quando vengono dichiarati in un assembly ritirabile. Non è possibile usare l'istruzione OpCodes.Calli nell'implementazione di un tipo in un assembly ritirabile e non è possibile eseguire il marshalling di tali tipi in codice non gestito. È comunque possibile effettuare chiamate nel codice nativo tramite un punto di ingresso dichiarato in un assembly non ritirabile.
Marshalling
Gli oggetti, in particolare i delegati, definiti in assembly ritirabili non possono essere sottoposti a marshalling. Si tratta di una restrizione per tutti i tipi creati temporanei.
Caricamento degli assembly
La reflection emit è l'unico meccanismo supportato per il caricamento degli assembly ritirabili. Gli assembly caricati con qualsiasi altra forma di caricamento non possono essere scaricati.
Oggetti legati al contesto
Le variabili statiche a livello di contesto non sono supportate. Non è possibile estendere i tipi in un assembly ritirabile ContextBoundObject. Tuttavia, il codice negli assembly ritirabili può usare oggetti associati al contesto definiti altrove.
Dati statici a livello di thread
Le variabili statiche a livello di thread non sono supportate.
Agli assembly ritirabili si applicano le seguenti restrizioni in .NET Framework e .NET nelle versioni precedenti a .NET 9:
Campi statici con
FixedAddressValueTypeAttribute
I campi statici definiti negli assembly ritirabilI non possono avere l'attributo FixedAddressValueTypeAttribute applicato.