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 può essere salvato, ed è soggetto alle limitazioni descritte nella sezione Restrizioni sugli 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 di T, 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 di T impedisce lo scaricamento.

  • Un riferimento statico a T da un altro tipo definito in modo dinamico T1 che è ancora raggiungibile mediante l'esecuzione del codice. Ad esempio, T1 potrebbe derivare da T o T potrebbe essere il tipo di un parametro in un metodo di T1.

  • Oggetto ByRef a un campo statico che appartiene a T.

  • RuntimeTypeHandle, RuntimeFieldHandle o RuntimeMethodHandle che fa riferimento a T o a un componente di T.

  • 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 per T può essere ottenuto da un tipo di matrice il cui tipo di elemento è T o da un tipo generico che ha T come argomento di tipo.

  • Un metodo M nello stack di chiamate di qualsiasi thread, in cui M è un metodo di T o un metodo a livello di modulo che viene definito nell'assembly.

  • 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.

Ai fini del rilevamento della durata, un tipo generico costruito, ad List<int> esempio (in C#) o List(Of Integer) (in Visual Basic) creato e usato nella generazione di un assembly collectible viene considerato definito nell'assembly che contiene la definizione di 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.

  • 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 raccoglibile. L'istruzione OpCodes.Calli non può essere utilizzata nell'implementazione di un tipo in un assembly raccoglibile e tali tipi non possono essere distribuiti al codice non gestito. Tuttavia, è possibile chiamare nel codice nativo usando un punto di ingresso dichiarato in un assembly non raccoglibile.

  • Marshalling

    Non è possibile eseguire il marshalling degli oggetti (in particolare i delegati) definiti negli assembly raccoglibili. Si tratta di una restrizione per tutti i tipi creati temporanei.

  • Caricamento degli assembly

    Reflection emit è l'unico meccanismo supportato per il caricamento di assembly raccoglibili. 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 del thread non sono supportate.

Vedi anche