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 ogni memoria gestita e non gestita utilizzata da un assembly ritirabile e dai tipi che contiene. Il nome dell'assembly e le altre informazioni simili vengono rimosse dalle tabelle interne.
Per abilitare lo scaricamento, utilizzare il contrassegno AssemblyBuilderAccess.RunAndCollect quando si crea un assembly dinamico. L'assembly è temporaneo (ovvero, non è possibile salvarlo) ed è soggetto alle limitazioni descritte nella sezione Limitazioni degli assembly ritirabili. Quando sono stati rilasciati tutti gli oggetti associati a un assembly ritirabile, Common Language Runtime (CLR) lo scarica automaticamente. Per tutti gli altri aspetti, le modalità di creazione e utilizzo degli assembly ritirabili sono uguali a quelle degli altri assembly dinamici.
Durata degli assembly ritirabili
La durata di un assembly dinamico sottoponibile a Garbage Collection viene controllata dall'esistenza di riferimenti ai tipi che contiene e dagli oggetti creati a partire da tali tipi. Common Language Runtime non scarica un assembly finché esiste uno o più degli elementi seguenti (T è uno dei tipi definiti nell'assembly):
Un'istanza di T.
Un'istanza di una matrice di T o un'istanza di un insieme generico che presenta T come uno dei propri argomenti di tipo, anche se tale matrice o insieme è vuoto.
Un'istanza di Type o TypeBuilder che rappresenta T.
Nota |
---|
È necessario rilasciare tutti gli oggetti che rappresentano parti dell'assembly.L'oggetto ModuleBuilder che ha definito T mantiene un riferimento a TypeBuilder e l'oggetto AssemblyBuilder mantiene un riferimento a ModuleBuilder. Pertanto, i riferimenti a questi oggetti devono essere rilasciati.Anche l'esistenza di un oggetto LocalBuilder o di un oggetto ILGenerator utilizzato nella costruzione di T impedisce lo scaricamento. |
Un riferimento statico a T da un altro tipo T1 definito dinamicamente che è ancora raggiungibile mediante l'esecuzione di codice. Ad esempio, T1 potrebbe derivare da T o T potrebbe essere il tipo di un parametro in un metodo di T1.
Un riferimento ByRef a un campo statico che appartiene a T.
Un oggetto RuntimeTypeHandle, RuntimeFieldHandle o RuntimeMethodHandle che fa riferimento a T o a un componente di T.
Un'istanza di qualsiasi oggetto reflection che può essere utilizzata indirettamente o direttamente per accedere all'oggetto Type che rappresenta T. Ad esempio, l'oggetto Type di T può essere ottenuto da un tipo di matrice il cui tipo di elemento è T o da un tipo generico che presenta T come argomento di tipo.
Un metodo M nello stack di chiamate di qualsiasi thread, dove M è un metodo di T o un metodo a livello di modulo definito nell'assembly.
Un delegato di un metodo statico definito in un modulo dell'assembly.
Se anche un solo elemento di questo elenco esiste per un solo tipo o un solo metodo nell'assembly, il runtime non può scaricare l'assembly.
Nota |
---|
Di fatto, il runtime scarica l'assembly solo dopo l'esecuzione dei finalizzatori per tutti gli elementi dell'elenco. |
Per tener traccia della durata, si considera che un tipo generico costruito quale List<int> (List(Of Integer) in Visual Basic) creato e utilizzato nella generazione di un assembly ritirabile sia stato definito nell'assembly che contiene la definizione di tipo generico oppure in un assembly che contiene la definizione di uno dei propri argomenti di tipo. L'assembly esatto utilizzato è un dettaglio di implementazione ed è soggetto a modifiche.
Limitazioni degli assembly ritirabili
Gli assembly ritirabili sono soggetti alle limitazioni seguenti:
Riferimenti statici I tipi in un assembly dinamico comune non possono presentare riferimenti statici ai tipi definiti in un assembly ritirabile. Ad esempio, se si definisce un tipo comune che eredita un tipo in un assembly ritirabile, viene generata un'eccezione NotSupportedException. Un tipo in un assembly ritirabile può presentare riferimenti statici a un tipo in un altro assembly ritirabile. Tuttavia, ciò estende la durata dell'assembly a cui si fa riferimento alla durata dell'assembly di riferimento.
Interoperabilità COM Nessuna interfaccia COM può essere definita all'interno di un assembly ritirabile. Inoltre, nessuna istanza di tipi all'interno di un assembly ritirabile può essere convertita in un oggetto COM. Un tipo in un assembly ritirabile non può fungere da COM Callable Wrapper (CCW) o Runtime Callable Wrapper (RCW). Tuttavia, i tipi negli assembly ritirabili possono utilizzare gli oggetti che implementano interfacce COM.
Platform invoke I metodi che presentano l'attributo DllImportAttribute non verranno compilati quando vengono dichiarati all'interno di un assembly ritirabile. L'istruzione OpCodes.Calli non può essere utilizzata nell'implementazione di un tipo in un assembly ritirabile e di tali tipi non può essere effettuato il marshalling a codice non gestito. Tuttavia, è possibile eseguire chiamate all'interno di codice nativo tramite un punto di ingresso dichiarato in un assembly non sottoponibile a Garbage Collection.
Marshalling Non è possibile eseguire il marshalling degli oggetti definiti negli assembly ritirabili (in particolare, dei delegati). Questa limitazione si applica a tutti i tipi generati temporanei.
Caricamento di assembly La reflection emit è l'unico meccanismo supportato per il caricamento degli assembly ritirabili. Gli assembly caricati mediante qualsiasi altra forma di caricamento di assembly non possono essere scaricati.
Oggetti associati al contesto Le variabili di contesto statico non sono supportate. I tipi in un assembly ritirabile non possono estendere ContextBoundObject. Tuttavia, il codice negli assembly ritirabili può utilizzare oggetti associati al contesto definiti altrove.
Dati statici a livello di thread Le variabili statiche a livello di thread non sono supportate.