Durante i miei esperimenti di generazione e compilazione dinamica di codice mi sto imbattendo in quella che non stenterei a definire una stranezza.
Genero al volo una classe che estende una classe base (definita nella libreria che genera il codice) e si riferisce ad un particolare tipo che varia di volta in volta e si trova probabilmente in un'altra libreria.
Al momento della generazione imposto tutti i riferimenti e le opzioni:
Dim provider As Microsoft.VisualBasic.VBCodeProvider
Dim compiler As System.CodeDom.Compiler.ICodeCompiler
Dim results As System.CodeDom.Compiler.CompilerResultsDim cp As New System.CodeDom.Compiler.CompilerParameters
cp.ReferencedAssemblies.Add("System.dll")
cp.ReferencedAssemblies.Add("System.Data.dll")
Presto particolare attenzione a riferire gli assembly (ed ogni eventuale loro dipendenza) che non si trovano nella GAC specificandone il loro percorso COMPLETO. Ed eccomi al punto saliente
cp.GenerateInMemory =
True
Ovvero comunico con questa opzione al compilatore che non desidero che l'assembly venga scritto su disco, ma che rimanga in memoria.
La generazione va a buon fine (sebbene l'assembly venga scritto su disco nella cartella temporanea) e non ci sono errori apparenti fino a quando uno dei riferimenti non si trova né nella GAC, né nella cartella dell'applicazione (é stato caricato dinamicamente da una cartella di plugin ad esempio). In tal caso quando si cerca di usare il tipo generato viene sollevata un eccezione che specifica l'impossibilità di trovare l'assembly di questo riferimento. Ho provato anche ad impostare la proprietà: cp.CompilerOptions = "libpath:""cartella della mia DLL""", ma continua a non funzionare finché non imposto:
cp.GenerateInMemory = False
E sì che alla fine dei conti il risultato é apparentemente lo stesso in quanto l'assembly viene comunque generato nella cartella temporanea (salvo diversa indicazione). Misteri di .NET!
UPDATE: spiego meglio viste le numerose domande.
A1 = Assembly del programma principale, contiene una classe PlugIn. Il programma ricerca in una particolare cartella assembly che contengano una classe che estende PlugIn e li carica
A2 = Assembly che contiene la classe MyPlugIn che eredita da A1.PlugIn. Dipende da A3
A3 = Assembly che contiene la classe UtilityBase (mustinherit). UtilityBase ha un metodo Shared che riceve un Type, genera del codice VB ottimizzato per tale tipo, compila questo codice in un assembly (chiamato AD)
Finché A1 ha un riferimento ad A2 (e questi si trova quindi nella stessa cartella di A1) FUNZIONA TUTTO. Il problema sorge quanto A1 carica A2 dinamicamente da un altro percorso in tal caso l'assembly generato AD da un errore in esecuzione (sì, non in compilazione) di tipo TypeLoadException: "impossibile trovare l'assembly A2". Per ovviare a questo problema basta impostare fra le opzioni di compilazione per AD GenerateInMemory = False. In ogni caso verrebbe generato un file temporaneo per l'assembly, quindi NON capisco proprio il perché di questo comportamento. Comunque, se aveste mai lo stesso problema... ;-)